教程:将 AWS Lambda 与 Amazon S3 结合使用 - AWS Lambda

教程:将 AWS Lambda 与 Amazon S3 结合使用

假设您要为上传到存储桶的每个图像文件创建一个缩略图。您可以创建一个 Lambda 函数 (CreateThumbnail),在创建对象后,Amazon S3 可调用该函数。之后,Lambda 函数可以从源存储桶读取图像对象并创建缩略图目标存储桶。

完成本教程后,您的账户中将具有以下 Amazon S3、Lambda 和 IAM 资源:

Lambda 资源

  • Lambda 函数。

  • 一个与 Lambda 函数关联的访问策略,此策略向 Amazon S3 授予调用 Lambda 函数的权限。

IAM 资源

  • 一个执行角色,此角色通过与其关联的权限策略授予您的 Lambda 函数所需的权限。

Amazon S3 资源

  • 具有调用 Lambda 函数的通知配置的源存储桶。

  • 函数在其中保存已调整大小的图像的目标存储桶。

先决条件

本教程假设您对基本 Lambda 操作和 Lambda 控制台有一定了解。如果尚不了解,请按照AWS Lambda 入门中的说明创建您的第一个 Lambda 函数。

为了遵循本指南中的步骤,您需要命令行终端或外壳,以便运行命令。命令显示在列表中,以提示符 ($) 和当前目录名称(如果有)开头:

~/lambda-project$ this is a command this is output

对于长命令,使用转义字符 (\) 将命令拆分到多行中。

在 Linux 和 macOS 中,可使用您首选的外壳程序和程序包管理器。在 Windows 10 中,您可以 安装 Windows Subsystem for Linux,获取 Ubuntu 和 Bash 与 Windows 集成的版本。

安装 npm 来管理函数的依赖关系。

本教程使用 AWS CLI 命令来创建和调用 Lambda 函数。安装 AWS CLI,并配置 AWS CLI 以便与您的 AWS 凭证结合使用

创建执行角色

创建执行角色,向您的函数授予访问 AWS 资源的权限。

创建执行角色

  1. 打开 IAM 控制台中的“角色”页面

  2. 选择 Create role (创建角色)

  3. 创建具有以下属性的角色。

    • 可信任的实体AWS Lambda

    • 权限AWSLambdaExecute

    • 角色名称 (角色名称)lambda-s3-role

AWSLambdaExecute 策略具有该函数在 Amazon S3 中管理对象并将日志写入 CloudWatch Logs 所需的权限。

创建存储桶并上传示例对象

按照以下步骤创建存储桶并上传对象。

  1. 打开 Amazon S3 控制台

  2. 创建两个存储桶。目标存储桶名称必须为后跟 -resizedsource,其中 source 是您希望用于源的存储桶的名称。例如,mybucketmybucket-resized

  3. 在源存储桶中,上传一个 .jpg 对象 HappyFace.jpg

    在连接到 Amazon S3 之前手动调用 Lambda 函数时,您要将示例事件数据传递到指定源存储桶和 HappyFace.jpg 作为新建对象的函数,因此您需要先创建此示例对象。

创建函数

以下示例代码接收 Amazon S3 事件输入并对其所包含的消息进行处理。它调整源存储桶中图像的大小并将输出保存到目标存储桶。

注意

有关使用其他语言的示例代码,请参阅 示例 Amazon S3 函数代码

例 index.js

// dependencies const AWS = require('aws-sdk'); const util = require('util'); const sharp = require('sharp'); // get reference to S3 client const s3 = new AWS.S3(); exports.handler = async (event, context, callback) => { // Read options from the event parameter. console.log("Reading options from event:\n", util.inspect(event, {depth: 5})); const srcBucket = event.Records[0].s3.bucket.name; // Object key may have spaces or unicode non-ASCII characters. const srcKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " ")); const dstBucket = srcBucket + "-resized"; const dstKey = "resized-" + srcKey; // Infer the image type from the file suffix. const typeMatch = srcKey.match(/\.([^.]*)$/); if (!typeMatch) { console.log("Could not determine the image type."); return; } // Check that the image type is supported const imageType = typeMatch[1].toLowerCase(); if (imageType != "jpg" && imageType != "png") { console.log(`Unsupported image type: ${imageType}`); return; } // Download the image from the S3 source bucket. try { const params = { Bucket: srcBucket, Key: srcKey }; var origimage = await s3.getObject(params).promise(); } catch (error) { console.log(error); return; } // set thumbnail width. Resize will set the height automatically to maintain aspect ratio. const width = 200; // Use the Sharp module to resize the image and save in a buffer. try { var buffer = await sharp(origimage.Body).resize(width).toBuffer(); } catch (error) { console.log(error); return; } // Upload the thumbnail image to the destination bucket try { const destparams = { Bucket: dstBucket, Key: dstKey, Body: buffer, ContentType: "image" }; const putResult = await s3.putObject(destparams).promise(); } catch (error) { console.log(error); return; } console.log('Successfully resized ' + srcBucket + '/' + srcKey + ' and uploaded to ' + dstBucket + '/' + dstKey); };

查看上述代码并注意以下内容:

  • 函数通过作为参数接收的事件数据获知源存储桶名称和对象键名称。如果对象为 .jpg 或 .png,则该代码会创建一个缩略图并将其保存到目标存储桶。

  • 该代码假定目标存储桶已存在,且其名称为源存储桶名称后跟字符串 -resized。例如,如果在事件数据中识别的源存储桶为 examplebucket,则代码假定您具有目标存储桶 examplebucket-resized

  • 对于所创建的缩略图,该代码会将其键名称派生为后跟源对象键名称的字符串 resized-。例如,如果源对象键为 sample.jpg,则代码会创建具有键 resized-sample.jpg 的缩略图对象。

部署程序包是包含 Lambda 函数代码和依赖项的 .zip 文件。

创建部署程序包

  1. 在 Linux 环境中打开命令行终端或 shell。确保本地环境中的 Node.js 版本与函数的 Node.js 版本相匹配。

  2. 将函数代码保存为名为 lambda-s3 的文件夹中的 index.js

  3. 使用 npm 安装 Sharp 库。对于 Linux,请使用以下命令。

    lambda-s3$ npm install sharp

    对于 macOS,请使用以下命令。

    lambda-s3$ npm install --arch=x64 --platform=linux --target=12.13.0 sharp

    完成此步骤后,文件夹结构如下:

    lambda-s3 |- index.js |- /node_modules/sharp └ /node_modules/...
  4. 创建包含函数代码和依赖项的部署包。

    lambda-s3$ zip -r function.zip .

创建函数

  • 使用 create-function 命令创建 Lambda 函数。

    $ aws lambda create-function --function-name CreateThumbnail \ --zip-file fileb://function.zip --handler index.handler --runtime nodejs12.x \ --timeout 10 --memory-size 1024 \ --role arn:aws:iam::123456789012:role/lambda-s3-role

如果您使用的是 AWS CLI 版本 2,请添加以下命令参数:

--cli-binary-format raw-in-base64-out

对于角色参数,请将编号序列替换为您的 AWS 账户 ID。之前的示例命令指定 10 秒超时值作为函数配置。根据上传的对象的大小,可能需要使用下面的 AWS CLI 命令增大超时值。

$ aws lambda update-function-configuration --function-name CreateThumbnail --timeout 30

测试 Lambda 函数

在本步骤中,您将使用示例 Amazon S3 事件数据手动调用 Lambda 函数。

测试 Lambda 函数

  1. 将下面的 Amazon S3 示例事件数据保存到某个文件中,并将该文件另存为 inputFile.txt。您需要提供 sourcebucket 名称和 .jpg 对象键来更新该 JSON。

    { "Records":[ { "eventVersion":"2.0", "eventSource":"aws:s3", "awsRegion":"us-west-2", "eventTime":"1970-01-01T00:00:00.000Z", "eventName":"ObjectCreated:Put", "userIdentity":{ "principalId":"AIDAJDPLRKLG7UEXAMPLE" }, "requestParameters":{ "sourceIPAddress":"127.0.0.1" }, "responseElements":{ "x-amz-request-id":"C3D13FE58DE4C810", "x-amz-id-2":"FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD" }, "s3":{ "s3SchemaVersion":"1.0", "configurationId":"testConfigRule", "bucket":{ "name":"sourcebucket", "ownerIdentity":{ "principalId":"A3NL1KOZZKExample" }, "arn":"arn:aws:s3:::sourcebucket" }, "object":{ "key":"HappyFace.jpg", "size":1024, "eTag":"d41d8cd98f00b204e9800998ecf8427e", "versionId":"096fKKXTRTtl3on89fVO.nfljtsv6qko" } } } ] }
  2. 运行下面的 Lambda CLI invoke 命令以调用函数。请注意,该命令会请求异步执行。(可选)可通过将 RequestResponse 指定为 invocation-type 参数值来同步调用它。

    $ aws lambda invoke --function-name CreateThumbnail --invocation-type Event \ --payload file://inputFile.txt outputfile.txt
  3. 验证目标存储桶中是否已创建缩略图。

配置 Amazon S3 以发布事件

在本步骤中,您将添加剩余的配置,以便 Amazon S3 能够向 AWS Lambda 发布对象创建事件并调用 Lambda 函数。您将在本步骤中执行以下操作:

  • 向 Lambda 函数访问策略添加权限以允许 Amazon S3 调用该函数。

  • 向源存储桶添加通知配置。在通知配置中,您需要提供以下内容:

    • 需要 Amazon S3 发布的事件的事件类型。在本教程中,您将指定 s3:ObjectCreated:* 事件类型,以便 Amazon S3 在创建对象时发布事件。

    • 要调用的 Lambda 函数。

向函数策略添加权限

  1. 运行下面的 Lambda CLI add-permission 命令以向 Amazon S3 服务委托人 (s3.amazonaws.com) 授予执行 lambda:InvokeFunction 操作的权限。请注意,向 Amazon S3 授予权限,使其只能在满足以下条件时调用该函数:

    • 在特定的存储桶上检测到对象创建事件。

    • 该存储桶由您的账户拥有。如果删除一个存储桶,则另一个账户可能会创建具有相同 ARN 的存储桶。

    $ aws lambda add-permission --function-name CreateThumbnail --principal s3.amazonaws.com \ --statement-id s3invoke --action "lambda:InvokeFunction" \ --source-arn arn:aws:s3:::sourcebucket \ --source-account account-id
  2. 通过运行 AWS CLI get-policy 命令验证函数的访问策略。

    $ aws lambda get-policy --function-name CreateThumbnail

在源存储桶上添加通知配置,以请求 Amazon S3 向 Lambda 发布对象创建事件。

重要

此过程将存储桶配置为每当在其中创建对象时调用您的函数。确保仅在源存储桶上配置此选项,并且不要通过触发的函数在源存储桶中创建对象。否则,您的函数可能会导致自身在循环中被连续调用

配置通知

  1. 打开 Amazon S3 控制台

  2. 选择源存储桶。

  3. 选择 Properties.

  4. Events (事件) 下,使用以下设置配置通知。

    • 名称lambda-trigger

    • 事件All object create events

    • 发送到Lambda function

    • LambdaCreateThumbnail

有关事件配置的更多信息,请参阅 Amazon Simple Storage Service 控制台用户指南 中的启用事件通知

测试设置

现在,可以按以下方式测试设置:

  1. 使用 Amazon S3 控制台将 .jpg 或 .png 对象上传到源存储桶。

  2. 使用 CreateThumbnail 函数验证是否在目标存储桶中创建了缩略图。

  3. 在 CloudWatch 控制台中查看日志。

清除资源

如果您不想保留为本教程创建的资源,可以立即将其删除。通过删除您不再使用的 AWS 资源,可防止您的 AWS 账户产生不必要的费用。

删除 Lambda 函数

  1. 打开 Lambda 控制台的“函数”页面

  2. 选择您创建的函数。

  3. 依次选择 ActionsDelete

  4. 选择删除

删除执行角色

  1. 打开 IAM 控制台的“角色”页面

  2. 选择您创建的执行角色。

  3. 选择删除角色

  4. 选择 Yes, delete (是,删除)

删除 S3 存储桶

  1. 打开 Amazon S3 控制台

  2. 选择您创建的源存储桶。

  3. 选择 Delete

  4. 在文本框中输入源存储桶的名称。

  5. 选择 Confirm