
1. 项目概述当大图遇上阿里云OSS的20M限制做Web开发或者内容管理的朋友估计都遇到过图片处理的麻烦事。用户上传的图片越来越大4K、8K甚至更高分辨率的照片、设计稿、扫描件动辄几十兆。如果直接把原图扔到页面上加载慢不说流量也吃不消。所以图片缩放、压缩是刚需。阿里云OSS对象存储服务提供了非常方便的图片处理服务通过简单的URL参数就能实现缩放、裁剪、水印等操作省去了自己搭建图片处理服务器的麻烦。但这里有个不大不小的“坑”OSS的图片处理服务对原图大小有个限制——不能超过20MB。一旦用户上传了一张30MB的高清大图你再用类似?x-oss-processimage/resize,w_800这样的参数去访问OSS就会直接返回一个错误告诉你原图太大处理不了。这个限制在官方文档里写得明明白白但对于很多业务场景来说用户上传的图片就是不可控的。你不能指望每个用户都懂技术会自己压缩好了再传。这个问题不解决前端页面可能直接裂开显示不出缩略图用户体验大打折扣。这个项目要解决的就是如何优雅地绕过这个20MB的限制确保无论用户上传多大的图片我们都能生成出可用的缩略图。核心思路其实不复杂既然OSS处理不了超过20MB的图那我们就在它处理之前先把大图“瘦身”到20MB以内。听起来简单但具体怎么做在哪里做用什么做里面就有不少门道了。是上传时同步处理还是访问时异步处理是用服务器端的ImageMagick/GD库还是用云函数处理后的中间图存不存存哪里这些都是需要仔细权衡的设计点。2. 核心方案设计与选型考量面对“大图无法缩放”这个问题我们有几个潜在的解决路径。首先得把各个方案的优缺点掰扯清楚才能做出最适合自己业务的选择。2.1 方案一上传时同步预处理客户端或服务端这是最直接的思路。在图片上传到OSS的那一刻就把它处理成符合要求的大小。客户端处理前端压缩利用HTML5的Canvas API或类似compressorjs这样的库在用户选择图片后、点击上传前在浏览器里进行压缩和缩放。优点是能极大减轻服务器压力和节省OSS存储空间因为传上去的就是小图。缺点也很明显依赖用户浏览器性能处理超大图如100MB可能导致页面卡顿甚至崩溃无法保证处理质量的一致性不同浏览器Canvas实现有细微差异最重要的是你丢失了原始大图。如果未来业务需要原图比如提供下载那就没办法了。服务端处理上传接口处理用户将图片上传到你的应用服务器服务器端用PHP的GD库或Imagick扩展对图片进行压缩再将处理后的图片上传到OSS。这个方案控制力强质量稳定也能保留原图如果你在服务器上也存一份的话。但它的瓶颈在于你的应用服务器处理大图是CPU和内存密集型操作会大量占用进程资源如果同时有几个用户上传大图服务器可能瞬间负载飙升影响其他接口的响应。而且这要求你的服务器有足够的临时存储空间来存放上传的原始文件。注意无论客户端还是服务端同步处理都会增加用户感知的“上传耗时”。用户需要等待处理完成才能得到上传成功的反馈对于大图这个等待时间可能很长体验不佳。2.2 方案二访问时异步处理服务端代理另一个思路是“懒处理”。平时不管当第一次有人请求某个图片的缩略图时如果发现原图超过20MB再触发处理流程。工作流程用户访问图片缩略图URL例如https://bucket.oss-cn-hangzhou.aliyuncs.com/path/to/image.jpg?x-oss-processimage/resize,w_800。我们的服务可以是一个单独的图片处理服务或云函数拦截这个请求。服务检查OSS上该图片的原图大小可通过OSS的HeadObject接口获取文件元信息。如果原图20MB直接重定向到OSS的图片处理URL由OSS完成。如果原图20MB则服务从OSS下载原图到临时空间使用Imagick进行缩放和压缩将处理结果一张小于20MB的、符合尺寸要求的“中间图”上传回OSS的另一个路径例如原路径加_cache后缀。后续所有相同的缩略图请求都直接指向这个已生成的“中间图”的OSS处理URL或者服务直接返回已处理好的图片二进制流。优势按需处理只有被访问到的图片才会被处理节省计算资源。无感上传用户上传原始大图的过程非常快体验好。保留原图原始文件完好无损地保存在OSS。挑战首次访问延迟第一次请求缩略图的用户会经历较长的等待因为要经历下载大图、处理、再上传的过程。需要做好“处理中”的占位图或加载状态。架构复杂度需要搭建一个高可用的服务来处理这些异步任务并管理“中间图”的生命周期缓存、更新、清理。2.3 方案三基于云函数的异步预处理这是方案二的升级版和云原生版特别适合服务器资源不充裕或者想追求弹性伸缩的场景。利用阿里云函数计算FC或Serverless应用引擎SAE在图片上传到OSS时自动触发一个处理函数。工作流程配置OSS的“事件通知”或“触发器”当有文件上传到指定目录如uploads/时自动调用一个预定义的云函数。云函数被触发收到事件信息包含Bucket名、文件Key等。云函数内下载新上传的图片检查大小。如果大于阈值如15MB留点余量则使用函数运行环境内的Imagick库进行压缩和生成标准缩略图例如800px宽质量80%。将处理好的“标准版”图片上传到OSS的另一个路径如processed/目录下同名文件这个“标准版”图片保证小于20MB。前端业务代码中所有需要缩放的图片都不再直接引用原图而是引用这个“标准版”图片的OSS处理URL。优势完全解耦图片处理与主应用服务器无关不会影响主站性能。弹性伸缩云函数自动应对处理峰值来多少图处理多少图处理完资源释放成本低。实时性好上传后即刻处理虽然异步但延迟通常很低秒级首次访问命中缓存的概率高。综合来看对于大多数追求稳定、可维护和弹性成本的Web应用方案三云函数异步预处理是目前最推荐的方式。它平衡了用户体验、系统架构和成本。方案二访问时代理适合处理频率不高、或对实时性要求不极致的场景。方案一同步处理则更适合对原图无要求、且上传并发量可控的小型应用。我们接下来的实操将重点围绕“方案三基于云函数的异步预处理”来展开同时也会介绍方案二中核心的图片处理代码因为这部分是相通的。3. 工具链与核心依赖解析工欲善其事必先利其器。要实现上述方案我们需要一套明确的工具链。这里以PHP环境为例进行说明因为从热搜词看PHP是相关的重要语境。3.1 核心处理工具ImageMagick vs GD库PHP里处理图片的两大巨头是ImageMagick通过imagick扩展和GD库。面对20MB以上的大图我们的选择几乎是唯一的。GD库PHP内置无需额外安装简单易用。但对于处理超大图片GD库有个致命弱点它需要将整个图片文件读入内存。一张30MB的RGB图片解码后在内存中占用的空间可能轻松超过100MB。这极易导致PHP进程内存超限Allowed memory size exhausted从而处理失败。ImageMagick (imagick)它是一个功能极其强大的独立软件PHP的imagick扩展是其接口。它的最大优势在于其流式处理和“懒加载”能力。ImageMagick在处理图片时并不一定需要将整张图加载到内存可以按需读取和处理部分数据这对处理大图来说至关重要能有效控制内存消耗。结论为了稳定可靠地处理超过20MB的图片必须使用ImageMagick (imagick扩展)。GD库更适合处理小图、简单的验证码或动态图形生成。3.2 环境与部署平台选择阿里云函数计算 (FC)这是实现“方案三”的首选。我们需要创建一个PHP运行环境的函数。优势无需管理服务器自动伸缩按量付费与OSS同属阿里云生态内网互通速度快配置触发器简单。注意点函数计算的运行环境是只读的除了/tmp目录且可能在不同请求间复用热启动或冷启动。我们需要在函数代码中处理好依赖安装如imagick和临时文件清理。传统云服务器 (ECS)或容器服务如果你选择“方案二”访问时代理或者希望有更强的控制力可以部署在ECS上。优势完全自主控制可以安装任何软件进行深度优化。劣势需要自行维护服务器、处理负载和伸缩性问题。Serverless应用引擎 (SAE)介于FC和ECS之间提供了一种更接近传统应用托管的方式同样支持弹性伸缩对于已有复杂PHP应用迁移上云比较友好。对于我们的目标阿里云函数计算 (FC)是最贴合“云原生”、“解耦”、“低成本”理念的选项。接下来的步骤将基于FC进行。3.3 关键阿里云服务与配置OSS (对象存储)存储原始大图和处理后的“标准版”图片。需要创建两个Bucket或者在一个Bucket内用不同前缀区分如origin/和processed/。需要配置好防盗链、生命周期规则如自动删除/tmp下的过期文件等。函数计算 (FC)执行图片处理逻辑。需要创建服务、函数并配置OSS触发器。访问控制 (RAM)为了安全必须创建一个具有最小权限的RAM角色如AliyunOSSFullAccess和AliyunFCFullAccess策略的子集并授权给FC函数使用。切勿使用主账号的AccessKey日志服务 (SLS)FC函数默认集成SLS用于查看处理日志和错误信息是排查问题的关键。4. 实操搭建基于函数计算的自动图片压缩流水线现在我们一步步搭建起整个系统。假设我们的业务场景是用户上传图片到OSS的user-uploads/origin/目录系统自动生成一个最长边为1600像素、质量优化后的版本存储到user-uploads/processed/目录此版本保证小于20MB可供后续任意OSS图片处理操作使用。4.1 步骤一准备PHP函数代码首先编写核心的图片处理函数。我们将它保存为index.php。?php // index.php use OSS\OssClient; use OSS\Core\OssException; // 初始化函数计算的环境变量 $endpoint getenv(OSS_ENDPOINT); // 例如: oss-cn-hangzhou-internal.aliyuncs.com (建议用内网Endpoint) $bucket getenv(OSS_BUCKET); $accessKeyId getenv(OSS_ACCESS_KEY_ID); $accessKeySecret getenv(OSS_ACCESS_KEY_SECRET); $processedPrefix getenv(PROCESSED_PREFIX, user-uploads/processed/); // 处理函数的主入口 function handler($event, $context) { global $endpoint, $bucket, $accessKeyId, $accessKeySecret, $processedPrefix; // 1. 解析OSS事件触发信息 $eventObj json_decode($event, true); if (empty($eventObj[events])) { echo Invalid event data.\n; return; } $ossEvent $eventObj[events][0]; $ossObj $ossEvent[oss]; $objectKey urldecode($ossObj[object][key]); // 被上传文件的Key $eventTime $ossEvent[eventTime]; echo sprintf(Processing object: %s at %s\n, $objectKey, $eventTime); // 定义只处理 origin/ 目录下的文件且是图片 $originPrefix user-uploads/origin/; if (strpos($objectKey, $originPrefix) ! 0) { echo Object not in target directory, skipped.\n; return; } $allowedExtensions [jpg, jpeg, png, gif, bmp, webp]; $extension strtolower(pathinfo($objectKey, PATHINFO_EXTENSION)); if (!in_array($extension, $allowedExtensions)) { echo Not an image file, skipped.\n; return; } // 2. 初始化OSS客户端 (使用内网Endpoint节省流量和延迟) try { $ossClient new OssClient($accessKeyId, $accessKeySecret, $endpoint, false); } catch (OssException $e) { printf(Create OSS client failed: %s\n, $e-getMessage()); return; } // 3. 获取文件信息判断大小 try { $objectMeta $ossClient-getObjectMeta($bucket, $objectKey); $fileSize $objectMeta[content-length]; echo sprintf(Original file size: %d bytes (%.2f MB)\n, $fileSize, $fileSize / 1024 / 1024); } catch (OssException $e) { printf(Get object meta failed: %s\n, $e-getMessage()); return; } $sizeThreshold 20 * 1024 * 1024; // 20MB阈值 if ($fileSize $sizeThreshold) { echo File size within limit, no need to pre-process.\n; // 可选即使小于20MB你也可以选择生成一个标准版统一源文件。 // return; } // 4. 下载原图到临时目录 (/tmp) $tempOriginalPath /tmp/ . basename($objectKey); try { $options array(OssClient::OSS_FILE_DOWNLOAD $tempOriginalPath); $ossClient-getObject($bucket, $objectKey, $options); echo Downloaded original file to: $tempOriginalPath\n; } catch (OssException $e) { printf(Download object failed: %s\n, $e-getMessage()); return; } // 5. 使用Imagick进行压缩处理 $tempProcessedPath /tmp/processed_ . basename($objectKey); $processSuccess processImage($tempOriginalPath, $tempProcessedPath, $extension); if (!$processSuccess) { echo Image processing failed.\n; unlink($tempOriginalPath); return; } // 6. 计算处理后的文件大小 $processedSize filesize($tempProcessedPath); echo sprintf(Processed file size: %d bytes (%.2f MB)\n, $processedSize, $processedSize / 1024 / 1024); // 7. 上传处理后的图片到 processed/ 目录 // 生成目标Key例如 user-uploads/origin/abc.jpg - user-uploads/processed/abc.jpg $processedKey $processedPrefix . substr($objectKey, strlen($originPrefix)); try { $ossClient-uploadFile($bucket, $processedKey, $tempProcessedPath); echo sprintf(Successfully uploaded processed image to: %s\n, $processedKey); } catch (OssException $e) { printf(Upload processed file failed: %s\n, $e-getMessage()); } // 8. 清理临时文件 unlink($tempOriginalPath); unlink($tempProcessedPath); echo Temporary files cleaned up.\n; } /** * 使用Imagick处理图片的核心函数 * param string $inputPath 输入文件路径 * param string $outputPath 输出文件路径 * param string $format 图片格式 * return bool 成功与否 */ function processImage($inputPath, $outputPath, $format) { try { $image new Imagick($inputPath); // 获取原图尺寸 $originalWidth $image-getImageWidth(); $originalHeight $image-getImageHeight(); $maxDimension 1600; // 我们设定的最大边长 // 计算等比例缩放后的尺寸 if ($originalWidth $originalHeight $originalWidth $maxDimension) { $newWidth $maxDimension; $newHeight intval($originalHeight * $maxDimension / $originalWidth); } elseif ($originalHeight $maxDimension) { $newHeight $maxDimension; $newWidth intval($originalWidth * $maxDimension / $originalHeight); } else { // 原图尺寸已经小于等于最大值但可能文件体积大如未压缩的PNG我们仍进行压缩优化 $newWidth $originalWidth; $newHeight $originalHeight; } // 执行缩放使用高质量滤波器 $image-resizeImage($newWidth, $newHeight, Imagick::FILTER_LANCZOS, 0.9, true); $image-stripImage(); // 移除EXIF等元信息减小文件体积 // 设置输出格式和压缩质量 $image-setImageFormat($format); switch (strtolower($format)) { case jpg: case jpeg: $image-setImageCompression(Imagick::COMPRESSION_JPEG); $image-setImageCompressionQuality(82); // 质量82是个较好的平衡点 $image-setInterlaceScheme(Imagick::INTERLACE_PLANE); // 渐进式JPEG break; case png: $image-setImageCompression(Imagick::COMPRESSION_ZIP); // PNG可以尝试设置压缩级别但效果不如JPEG的quality参数直观 // $image-setImageCompressionQuality(90); // 这个对PNG意义不大 // 更有效的是减少颜色深度如果图片允许 // $image-setImageDepth(8); break; case webp: $image-setImageCompression(Imagick::COMPRESSION_WEBP); $image-setImageCompressionQuality(80); break; // GIF和BMP通常不作为大图存储格式这里简单处理 } // 写入输出文件 $result $image-writeImage($outputPath); $image-clear(); $image-destroy(); if (!$result) { echo Imagick failed to write image.\n; return false; } return true; } catch (ImagickException $e) { printf(Imagick processing failed: %s\n, $e-getMessage()); return false; } catch (Exception $e) { printf(General processing error: %s\n, $e-getMessage()); return false; } }4.2 步骤二创建函数计算服务与函数登录阿里云控制台进入函数计算FC。创建服务服务是函数的逻辑分组。创建一个新服务例如image-processor。在“高级配置”中务必配置一个服务角色。这个角色需要拥有读取源OSS Bucket和写入目标目录的权限。你可以使用AliyunOSSFullAccess策略但更安全的做法是创建自定义策略精确授权到具体的Bucket和目录。创建函数选择“使用自定义运行时创建”。运行环境选择PHP 8.2根据你的需求选择确保支持imagick。上传代码方式选择“通过文件夹上传”将包含index.php和composer.json的文件夹打包成ZIP。composer.json示例{ require: { aliyuncs/oss-sdk-php: ^2.4 } }在“函数配置”中设置执行超时时间。处理大图可能耗时建议设置为30-60秒。内存规格建议设置为512MB或1024MBImagick处理大图需要足够内存。在“环境变量”中添加步骤一代码中引用的几个变量OSS_ENDPOINT: 你的OSS Bucket的内网Endpoint强烈建议用内网速度快且免费。OSS_BUCKET: 你的Bucket名称。OSS_ACCESS_KEY_ID/OSS_ACCESS_KEY_SECRET: 通过服务角色关联这里可以不填函数会通过角色临时密钥访问。但我们的代码示例用了环境变量你也可以选择在代码中通过$context获取临时令牌这是更推荐的做法。为简化我们先使用环境变量但需在角色中配置好权限。PROCESSED_PREFIX: 处理后的文件存放前缀如user-uploads/processed/。4.3 步骤三配置OSS事件触发器在创建好的函数详情页进入“触发器”标签页。点击“创建触发器”。触发器类型选择 “OSS”。选择你存储原图的Bucket。触发事件选择PutObject即文件上传完成时。前缀填写user-uploads/origin/后缀可以根据需要填写如.jpg,.png等不填则匹配所有。勾选“立即启用”。点击确定。至此整个自动化流水线就配置完成了。当有图片上传到user-uploads/origin/目录时函数会被自动触发下载图片、压缩处理、并上传到user-uploads/processed/目录。4.4 步骤四前端应用改造最后一步是修改你的Web应用。所有需要显示缩略图或进行图片处理的地方不再直接引用原图路径而是引用处理后的“标准版”图片路径。原逻辑会出问题https://your-bucket.oss-region.aliyuncs.com/user-uploads/origin/photo.jpg?x-oss-processimage/resize,w_400新逻辑稳定可靠https://your-bucket.oss-region.aliyuncs.com/user-uploads/processed/photo.jpg?x-oss-processimage/resize,w_400因为processed/photo.jpg已经是经过我们函数处理过的、保证小于20MB的图片所以OSS的图片处理服务可以毫无压力地对其进行二次处理缩放、裁剪等。5. 核心环节Imagick处理参数的深度调优上面代码中的processImage函数是核心。里面有几个关键参数直接影响输出图片的质量和大小需要根据业务仔细调整。5.1 缩放策略与滤波器选择$image-resizeImage($newWidth, $newHeight, Imagick::FILTER_LANCZOS, 0.9, true);FILTER_LANCZOS这是Imagick中质量最高的缩放滤波器之一尤其适合缩小图片能很好地保留细节和锐度。虽然计算量稍大但对于一次性预处理任务来说完全值得。其他可选滤波器如FILTER_TRIANGLE速度更快但质量稍差。第五个参数true表示保持宽高比。这非常重要防止图片变形。5.2 图片质量与压缩的权衡JPEG质量 (setImageCompressionQuality)82是一个经验值。在肉眼难以察觉画质损失的前提下能显著减小文件体积。你可以尝试在75-90之间调整。低于75画质损失可能较明显高于90则文件体积增长很快性价比低。渐进式JPEG (setInterlaceScheme)启用后图片会以从模糊到清晰的方式加载虽然文件体积可能增加1-5%但能提升用户感知的加载速度体验更好。stripImage()这个操作至关重要。它移除所有EXIF、ICC配置文件、注释等元数据。一张手机拍的照片EXIF信息可能就占了几十KB甚至更多。移除它们能安全地减小文件体积且通常不影响网页显示。但要注意如果你的业务需要保留GPS、拍摄时间等信息就不能调用这个方法。PNG处理PNG是无损压缩对于截图、图标、带透明通道的图片很友好但对于照片类内容体积会远大于JPEG。如果原图是PNG格式的照片可以考虑在预处理中转换为JPEGsetImageFormat(‘jpg’)能获得巨大的体积缩减。对于必须用PNG的图片可以尝试$image-setImageDepth(8)减少颜色深度和$image-setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE)移除透明通道如果不需透明。5.3 内存限制与超大图处理即使使用Imagick处理极端大图如几百MB的TIFF格式航拍图也可能遇到内存问题。可以在函数代码开头增加内存限制并利用Imagick的像素缓存限制。// 在processImage函数开始处或handler开始处 ini_set(memory_limit, 1024M); // 根据函数配置的内存适当调整 // 在实例化Imagick对象后可以设置像素缓存限制以像素为单位 // $image-setResourceLimit(Imagick::RESOURCETYPE_MEMORY, 256 * 1024 * 1024); // 256MB // $image-setResourceLimit(Imagick::RESOURCETYPE_MAP, 512 * 1024 * 1024); // 512MB更稳健的做法是在处理前先通过$image-pingImage($inputPath)获取图片信息而不加载像素数据如果发现尺寸超乎寻常如超过10000x10000可以采取更激进的缩放策略或直接放弃处理记录错误。6. 常见问题、排查技巧与优化实录在实际部署和运行中你肯定会遇到各种各样的问题。下面是我踩过的一些坑和总结的排查技巧。6.1 函数执行失败日志报错“Unable to open image”可能原因1Imagick扩展未安装或不支持该图片格式。排查在函数本地测试环境中用php -m | grep imagick检查扩展是否加载。用Imagick::queryFormats()查看支持的格式。解决确保FC的PHP运行时预装了imagick扩展。阿里云官方PHP运行时通常已安装。如果格式不支持需要在函数层通过自定义Docker镜像或层(Layer)来安装额外的Imagick编解码器。可能原因2下载的临时文件损坏或权限问题。排查在函数日志中打印出下载后的临时文件路径和filesize看是否与OSS上的一致。检查/tmp目录是否可写。解决确保OSS客户端下载成功。函数计算的/tmp目录是可写的但空间有限通常512MB要确保处理完成后及时清理。6.2 处理后的图片体积仍然很大接近或超过20MB可能原因1缩放的目标尺寸设置得太大。排查检查代码中的$maxDimension如1600。对于手机屏幕1080或1200可能就够了。对于只是生成列表缩略图的场景800甚至更小都可以。解决根据实际显示需求降低最大边长。可以设计多级预处理生成多个尺寸的标准图如_large,_medium,_small。可能原因2图片格式和压缩参数不当。排查一张纯色或简单图形的PNG可能很小但一张彩色丰富的照片用PNG格式就会巨大。解决实现一个智能格式转换。例如如果原图是PNG/JPG且非透明统一输出为JPEG。对于WebP格式浏览器支持度已很高压缩率更好可以优先考虑。// 简单的格式转换逻辑示例 $outputFormat $format; if (in_array($format, [png, jpg, jpeg, bmp])) { // 检查图片是否有透明通道 if ($format png $image-getImageAlphaChannel() Imagick::ALPHACHANNEL_UNDEFINED) { // PNG但没有透明通道转为JPEG $outputFormat jpg; } elseif ($format png) { // 有透明通道保留PNG但尝试优化 $image-setImageFormat(png); // PNG优化可以尝试使用 optipng 或 pngquant 命令行工具但FC环境可能需额外安装 } } // 如果客户端支持可以考虑统一输出为WebP // $outputFormat webp;6.3 函数执行超时可能原因原图非常大如超过50MB下载或处理时间超过了函数配置的超时时间默认3秒我们之前建议设30-60秒。排查查看SLS日志中的函数执行时长。如果接近超时时间就是这个问题。解决增加超时时间在函数配置中适当增加如120秒。但要考虑FC的最大超时限制通常为10分钟。优化处理逻辑如果图片尺寸不大但文件体积大如未压缩的BMPstripImage()和设置正确的压缩质量是关键。分治策略对于极端情况可以考虑在函数中只进行轻量判断和任务分发将实际的重型处理任务发送到消息队列如RocketMQ由另一个专门的高配置、长时运行的服务来处理。但这增加了架构复杂度。6.4 “中间图”缓存的管理与更新我们的方案生成了processed/下的图片。如果用户重新上传了同名文件覆盖了原图我们需要更新处理后的版本。方案一简单覆盖OSS触发器在文件覆盖PutObject时也会触发。我们的函数会重新处理并上传到processed/路径覆盖旧文件。这是最简单直接的方式。方案二版本管理如果业务需要保留历史版本可以在原图路径中包含版本信息如时间戳或唯一ID这样processed/下的路径也不同自然就是新版本。旧版本的文件可以通过OSS生命周期规则自动过期删除。6.5 内网Endpoint与成本优化在函数代码中连接OSS时务必使用内网Endpoint形如oss-cn-hangzhou-internal.aliyuncs.com。这有两大好处速度极快函数计算与OSS在同地域内网通信延迟极低。零流量费用阿里云同地域内网流量是免费的可以节省可观的公网下行流量费用。获取内网Endpoint的方法在OSS Bucket的“概览”页面“访问端口”区域可以看到“内网Endpoint”。6.6 监控与告警任何线上服务都需要监控。函数执行指标在FC控制台查看函数的调用次数、错误次数、平均耗时等。设立云监控告警当错误率超过阈值或平均耗时异常增长时发送通知。OSS存储监控监控processed/目录的存储量增长情况预估成本。自定义业务日志在函数代码中关键节点如开始处理、下载完成、处理完成、上传完成打印日志便于追踪单个图片的处理流水线。使用echo或error_log输出的内容都会汇集到函数的SLS日志中。通过以上这套组合拳我们不仅解决了“阿里云图片超过20M无法缩放”的具体问题更是构建了一个弹性、可靠、低成本的图片预处理云原生架构。这个架构可以轻松扩展未来如果需要增加智能鉴黄、添加水印、内容识别等功能只需在云函数处理链中增加相应的步骤即可。