亚马逊AWS官方博客

在亚马逊云科技中国区域利用 S3  Object Lambda 轻松实现自定义图片缩放

在网站开发中,不同终端设备往往需要不同分辨率的图片资源。传统做法是预先存储多种尺寸的图片,但这会增加存储成本和管理复杂度, 利用中国区已上线的 S3 Object Lambda 功能,我们可以实现动态图片缩放:

  • 按需生成任意尺寸的图片
  • 无需预存多个版本
  • 利用 S3 内置功能, 不用维护额外的 API 接口
  • 通过文件名参数直接指定目标尺寸

该方案既节省了存储空间,又简化了图片管理流程,让图片缩放变得更加灵活高效

方案架构

  1. 用户如需要访问S3 原始文件, 如 image1.jpg, 直接调用 S3 bucket 的 get object 方法即可.
  2. 用户如需要对 S3 中的图片文件进行指定分辨率的缩放, 则调用 S3 Object Lambda Access Point 并将 key 指定为 image1_300x200.jpg

实现步骤

本方案测试步骤选择宁夏区域 (cn-northwest-1)部署, 您也可以选择北京区域 (cn-north-1).

  1. 创建存储桶, 设为 image-resize-bucket01 并上传一个图片文件, 测试图片文件可在代码仓库中下载 image1 (默认分辨率为1280×720)
  2. 创建 S3 Access Point, name设为 s3-access-point 配置如下:

a. Data source: image-resize-bucket01
b. Network origin: Internet
c. Block all public access (推荐测试时使用)
d. Access Point policy (测试时不添加 policy, 保持空白)

  1. 创建 Lambda Function Execution Role, name 设为 ResizeImageObjectLambdaRole

a. Trust relationships:
b.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

c. Permission policies (创建自定义policy, 方案测试中没有指定 Resource, 生产环境中需要指定)
d.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "s3-object-lambda:WriteGetObjectResponse",
                "s3:Get*",
                "s3:List*",
                "s3:Describe*"
            ],
            "Resource": "*"
        }
    ]
}
  1. 创建 Lambda function, name设为 resize-image-lambda, 配置如下:

a. Runtime: python3.11
b. Architecture: x86_64
c. Execution role: 选用上一步创建的role
d. 创建完成后上传 zip文件.
e.

f. 上传后会自动部署代码.

  1. 创建Object Lambda Access Point, name 设为 resize-image-olap

a. Supporting Access Point: 选择上述步骤中创建的 s3-access-point
b. S3 APIs: GetObject
c. Invoke Lambda function: resize-image-lambda
d. Object Lambda Access Point policy, 本方案测试中不进行设置, 保持空
e. Block all public access (推荐测试时使用)

功能测试

取 Object Lambda Access Point 的 ARN:

AWS CLI:

aws s3api get-object --bucket {your_arn} --key image1_300x200.png image1.png

Boto3 api:

import boto3
import logging

# 用户配置参数
REGION_NAME = 'cn-northwest-1'
BUCKET_ARN = {your_arn}
SOURCE_KEY = 'image1_300x200.jpg'
LOCAL_FILENAME = 'image1.jpg'

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

def get_object_boto3():
    try:
        s3 = boto3.client('s3', region_name=REGION_NAME)
        logger.info(f"开始下载文件: {SOURCE_KEY}")
        
        response = s3.get_object(Bucket=BUCKET_ARN, Key=SOURCE_KEY)
        
        with open(LOCAL_FILENAME, 'wb') as f:
            f.write(response['Body'].read())
        
        logger.info(f"文件下载成功: {LOCAL_FILENAME}")
        
    except Exception as e:
        logger.error(f"下载文件失败: {str(e)}")
        raise

if __name__ == "__main__":
    get_object_boto3()

价格估算

假设图片大小平均为 200kb, 每次调用后下载的图片大小也为调用一次的价格分为如下几个部分:

  1. S3 api get-object 调用费用: ¥ 0.0000015 每笔请求
  2. Lambda 调用费用:  0.0000567 (512mb/GB 每秒) + 0.00000136 每次调用
  3. DTO (Data Transfer Out):  0.933 /GB

假设每次调用耗时 1 s, 则1000次调用费用为 ¥0.24, 其中约 80%为 DTO 费用.

总结与展望

该方案简单易用, 只需配置 S3 相关功能和 Lambda 而无需引入额外服务. 以下是可以优化的方向:

成本优化

  1. 如上文价格估算所述, 可以考虑压缩图片以降低 DTO 成本.
  2. Lambda 基础配置可以进行评估和优化, 并非每次任务都需要 512 MB 以上内存.
  3. 可以打包 ARM 版本的 Lambda Function 以降低成本.

性能优化

  1. 每次调用Object Lambda 时 Lambda 冷启动可能会造成较高延时, 可以考虑使用Lambda预置并发, 但成本也会相应上升.
  2. 可以优化 Lambda Function 的 resize image 逻辑, 测试不同图片处理库以及不同编程语言.

相关链接:

*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。

本篇作者

李永乐

亚马逊云科技解决方案架构师,专注于各行业的生成式 AI 解决方案的架构咨询和设计。在加入亚马逊云科技之前,曾就职于微软、惠普软件等企业,具有丰富的云计算实践经验。