AWS Lambda
开发人员指南
AWS 服务或AWS文档中描述的功能,可能因地区/位置而异。点 击 Getting Started with Amazon AWS to see specific differences applicable to the China (Beijing) Region.

AWS Lambda@Edge

利用 Lambda@Edge,您可以在 AWS 区域和 Amazon CloudFront 边缘站点运行 Lambda 函数以响应 CloudFront 事件,而无需配置或管理服务器。您可以在以下时间点使用 Lambda 函数来更改 CloudFront 请求和响应:

  • 在 CloudFront 收到查看器的请求之后 (查看器请求)

  • 在 CloudFront 将请求转发到源之前 (源请求)

  • 在 CloudFront 收到来自源的响应之后 (源响应)

  • 在 CloudFront 将响应转发到查看器之前 (查看器响应)

 显示 CloudFront 事件如何能够触发 Lambda 函数的概念图。

您也可以生成对查看器的响应,而不必将请求发送到源。

在 Node.js 6.10 中编写 CloudFront 的 Lambda 函数。使用 Lambda@Edge,您可构建多种解决方案,例如:

  • 检查 Cookie,从而重写站点不同版本的 URL 以进行 A/B 测试。

  • 根据 User-Agent 标头将不同的对象发送给您的用户,该标头包含有关提交请求的设备的信息。例如,您可以根据用户的设备向用户发送分辨率不同的图像。

  • 检查标头或授权令牌,在将请求转发到源之前插入一个相应的标头并允许访问控制。

  • 添加、删除和修改标头,然后重写 URL 路径,将用户定向到缓存中的不同对象。

  • 生成新的 HTTP 响应,将未经身份验证的用户重定向到登录页面,直接从边缘创建和交付静态网页,或执行其他操作。有关更多信息,请参阅 Amazon CloudFront 开发人员指南 中的使用 Lambda 函数生成对查看器和源请求的 HTTP 响应

有关使用 Lambda@Edge 设置 CloudFront 的更多信息,包括示例代码,请参阅 Amazon CloudFront 开发人员指南 中的结合使用 CloudFront 和 Lambda@Edge

如何为 Lambda@Edge 创建 Lambda 函数

下面概述了如何为 Lambda@Edge 创建 Lambda 函数:

  1. 使用 Node.js 6.10 为您的 Lambda 函数编写代码。

  2. 使用 AWS Lambda 控制台在 美国东部(弗吉尼亚北部)地区 中创建 Lambda 函数。(您也可以通过编程方式创建函数,例如,通过使用某个 AWS 软件开发工具包。)在创建函数时,指定以下值:

    • 要应用函数的 CloudFront 分配

    • 分配中的缓存行为

  3. 发布带编号的函数版本。

    如果要编辑函数,请在 美国东部(弗吉尼亚北部)地区 中对其进行编辑。然后发布带编号的新版本。

  4. 指定促使函数执行的一个或多个 CloudFront 事件 (称作触发器)。例如,您可以创建在 CloudFront 收到查看器的请求时促使函数执行的触发器。

    创建触发器时,Lambda 会将函数复制到全球范围内的 AWS 区域和 CloudFront 边缘站点。

 显示如何创建与 CloudFront 集成的 Lambda 函数的概念图。

设置 Lambda@Edge 的 IAM 权限和角色

要配置 Lambda@Edge,您需要 IAM 权限和 IAM 执行角色:

将 Lambda 函数与 CloudFront 分配关联所需的 IAM 权限

除了使用 AWS Lambda 所需的 IAM 权限之外,您还需要以下 IAM 权限才能将 Lambda 函数与 CloudFront 分配关联:

  • lambda:GetFunction

    对于资源,请指定当 CloudFront 事件发生时要执行的函数版本的 ARN,如以下示例所示:

    arn:aws:lambda:us-east-1:123456789012:function:TestFunction:2

  • lambda:EnableReplication*

    对于资源,请指定当 CloudFront 事件发生时要执行的函数版本的 ARN,如以下示例所示:

    arn:aws:lambda:us-east-1:123456789012:function:TestFunction:2

  • iam:CreateServiceLinkedRole

  • cloudfront:UpdateDistribution 或者 cloudfront:CreateDistribution

    选择 cloudfront:UpdateDistribution 来更新分配,或选择 cloudfront:CreateDistribution 来创建分配。

有关更多信息,请参阅以下文档:

执行角色

您必须创建一个可由服务委托人 lambda.amazonaws.comedgelambda.amazonaws.com 担任的 IAM 角色。当服务委托人执行您的函数时,由他们担任此角色。有关更多信息,请参阅 IAM 用户指南 的主题“AWS 工作职能托管策略”中的创建角色并附加策略 (控制台)

以下是角色信任策略的一个示例:

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

有关您需要向执行角色授予的权限的信息,请参阅 AWS Lambda Developer Guide 中的管理权限:使用 IAM 角色 (执行角色)。请注意以下几点:

  • 默认情况下,每当 CloudFront 事件触发 Lambda 函数时,数据都会写入 CloudWatch Logs。如果要使用这些日志,执行角色需要权限来将数据写入 CloudWatch Logs。您可以使用预定义的 AWSLambdaBasicExecutionRole 向执行角色授予权限。

    有关 CloudWatch Logs 的更多信息,请参阅 Amazon CloudFront 开发人员指南 中的 Lambda 函数的 CloudWatch 指标和 CloudWatch Logs

  • 如果您的 Lambda 函数代码访问其他 AWS 资源,比如从 S3 存储桶读取对象,则执行角色需要权限来执行此操作。

AWSServiceRoleForLambdaReplicator 角色

当您首次创建触发器时,会自动创建一个名为 AWSServiceRoleForLambdaReplicator 的角色,以允许 Lambda 将 Lambda@Edge 函数复制到 AWS 区域。需要此角色才能使用 Lambda@Edge。AWSServiceRoleForLambdaReplicator 角色的 ARN 与以下内容类似:

arn:aws:iam::123456789012:role/aws-service-role/replicator.lambda.amazonaws.com/AWSServiceRoleForLambdaReplicator

创建 Lambda@Edge 函数

要设置 AWS Lambda 以运行基于 CloudFront 事件的 Lambda 函数,请执行以下步骤。

创建 Lambda@Edge 函数

  1. 通过以下网址登录 AWS 管理控制台并打开 AWS Lambda 控制台:https://console.amazonaws.cn/lambda/

  2. 如果您已有一个或多个 Lambda 函数,请选择 Create function

    如果您没有任何函数,请选择 Get Started Now

  3. 在页面顶部的区域列表中,选择 美国东部(弗吉尼亚北部)

  4. 使用您自己的代码创建函数,或者以 CloudFront 蓝图为基础创建函数。

    • 要使用您自己的代码创建函数,请选择 Author from scratch

    • 要显示 CloudFront 蓝图列表,请在筛选条件字段中键入 cloudfront,然后按 Enter

      如果您找到了自己要使用的蓝图,请选择该蓝图的名称。

  5. Basic information 部分中,指定以下值:

    名称

    为函数键入一个名称。

    角色

    选择 Create new role from template(s)

    注意

    选择此值将使您能够迅速入手。或者,也可以选择 Choose an existing roleCreate a custom role。如果您选择以上选项之一,请按照提示填写此部分的信息。

    角色名称

    键入角色名称。

    Policy templates

    选择 Basic Edge Lambda permissions

  6. 如果您在步骤 4 中选择了 Author from scratch,请跳至步骤 7。

    如果您在步骤 4 中选择了蓝图,则可通过 cloudfront 部分创建一个触发器,它可将此函数与 CloudFront 分配和 CloudFront 事件中的缓存相关联。我们建议您现在选择 Remove,因此在创建函数时没有函数触发器。您可以在稍后添加触发器。

    重要

    建议您先测试和调试函数,然后再添加触发器。如果选择立即添加触发器,则在您创建好函数并且它完成向 AWS 区域和边缘站点的复制,且部署了相应的分配后,函数将立即开始运行。

  7. 选择 Create function

    Lambda 将创建两个版本的函数:$LATEST 和 Version 1。您只能编辑 $ LATEST 版本,但控制台最初会显示 Version 1。

  8. 要编辑函数,请选择页面顶部附近、函数 ARN 下方的 Version 1。然后,在 Versions 选项卡上,选择 $LATEST。(如果您离开再返回到该函数,则按钮标签将是 Qualifiers。)

  9. Configuration 选项卡上,选择适用的 Code entry type。然后,按照提示编辑或上传您的代码。

  10. 对于Runtime,请接受默认值 Node.js 6.10

  11. Tags 部分中,添加任何适用的标签。

  12. 选择 Actions,然后选择 Publish new version

  13. 键入新版本函数的说明。

  14. 选择 Publish

  15. 测试并调试函数。有关更多信息,请参阅下列内容:

  16. 当您准备好为 CloudFront 事件执行函数时,发布另一个版本并编辑该函数以添加触发器。有关更多信息,请参阅 为 Lambda@Edge 编辑 Lambda 函数

为 Lambda@Edge 函数添加触发器 (AWS Lambda 控制台)

创建 Lambda 函数时,您仅能指定一个触发器 — 仅 CloudFront 分配、缓存行为和导致函数执行的事件的一个组合。通过使用 Lambda 控制台或在 CloudFront 控制台中编辑分配,您可为同一个函数添加更多触发器:

  • 要使用 Lambda 控制台,请执行以下步骤。如果您要将更多触发器添加到同一 CloudFront 分配的函数中,则此方法非常有效。

  • 要使用 CloudFront 控制台,请参阅 Amazon CloudFront 开发人员指南 中的将 CloudFront 事件的触发器添加到 Lambda 函数中。如果要为多个分配添加触发器,则此方法非常有效,因为这样更易于查找您要更新的分配。您同时还可以更新其他 CloudFront 设置。

将触发器添加到 Lambda@Edge 函数 (AWS Lambda 控制台)

  1. 通过以下网址登录 AWS 管理控制台并打开 AWS Lambda 控制台:https://console.amazonaws.cn/lambda/

  2. 在页面顶部的区域列表中,选择 美国东部(弗吉尼亚北部)

  3. Functions 页面上,选择您要为其添加触发器的函数的名称。

  4. 选择 Qualifiers,然后选择 Versions 选项卡。

  5. 选择您要为其添加触发器的版本。

    重要

    您无法为 $LATEST 版本创建触发器,而必须为带编号的版本创建它们。

    选择某个版本后,相应按钮的名称会更改为 Version: $LATESTVersion: 版本号

  6. 选择 Triggers 选项卡。

  7. 选择 Add triggers

  8. Add trigger 对话框中,选择虚线框,然后再选择 CloudFront

    注意

    如果您已创建一个或多个触发器,则 CloudFront 为默认服务。

  9. 指定以下值,以指示您希望 Lambda 函数何时执行。

    分配 ID

    选择要向其中添加触发器的分配的 ID。

    Cache behavior

    选择缓存行为,该行为将指定您要对其执行函数的对象。

    CloudFront event

    选择促使函数执行的 CloudFront 事件。

    Enable trigger and replicate

    选中此复选框,以便 AWS Lambda 将函数复制到全球各地的区域。

  10. 选择 Submit

    在更新的 CloudFront 分配部署后,函数开始处理指定 CloudFront 事件的请求。要确定是否已部署分配,请在导航窗格中选择 Distributions。部署分配后,该分配的 Status 列的值会从 In Progress 更改为 Deployed

为 Lambda@Edge 编写函数

将 Node.js 用于 Lambda@Edge 的编程模型与在 AWS 区域内使用 Lambda 的编程模型相同。有关更多信息,请参阅 编程模型 (Node.js)

有关为 Lambda@Edge 编写函数的更多信息,请参阅 Amazon CloudFront 开发人员指南 中的 Lambda 函数的要求和限制

建议您包括 callback 参数并返回适用的对象:

示例:A/B 测试

以下示例演示了如何使用 Lambda@Edge 进行 A/B 测试。

Copy
'use strict'; exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; const headers = request.headers; if (request.uri !== '/experiment-pixel.jpg') { // do not process if this is not an A-B test request callback(null, request); return; } const cookieExperimentA = 'X-Experiment-Name=A'; const cookieExperimentB = 'X-Experiment-Name=B'; const pathExperimentA = '/experiment-group/control-pixel.jpg'; const pathExperimentB = '/experiment-group/treatment-pixel.jpg'; /* * Lambda at the Edge headers are array objects. * * Client may send multiple Cookie headers, i.e.: * > GET /viewerRes/test HTTP/1.1 * > User-Agent: curl/7.18.1 (x86_64-unknown-linux-gnu) libcurl/7.18.1 OpenSSL/1.0.1u zlib/1.2.3 * > Cookie: First=1; Second=2 * > Cookie: ClientCode=abc * > Host: example.com * * You can access the first Cookie header at headers["cookie"][0].value * and the second at headers["cookie"][1].value. * * Header values are not parsed. In the example above, * headers["cookie"][0].value is equal to "First=1; Second=2" */ let experimentUri; if (headers.cookie) { for (let i = 0; i < headers.cookie.length; i++) { if (headers.cookie[i].value.indexOf(cookieExperimentA) >= 0) { console.log('Experiment A cookie found'); experimentUri = pathExperimentA; break; } else if (headers.cookie[i].value.indexOf(cookieExperimentB) >= 0) { console.log('Experiment B cookie found'); experimentUri = pathExperimentB; break; } } } if (!experimentUri) { console.log('Experiment cookie has not been found. Throwing dice...'); if (Math.random() < 0.75) { experimentUri = pathExperimentA; } else { experimentUri = pathExperimentB; } } request.uri = experimentUri; console.log(`Request uri set to "${request.uri}"`); callback(null, request); };

示例:HTTP 重定向

以下示例演示了如何使用与 CloudFront 查看器请求和源请求事件相关联的 Lambda 函数生成 HTTP 重定向响应。如果您将函数与源请求相关联,则会缓存响应。

注意

您可以只针对查看器请求和源请求事件生成 HTTP 响应。有关更多信息,请参阅 Amazon CloudFront 开发人员指南 中的生成 HTTP 响应

Copy
'use strict'; exports.handler = (event, context, callback) => { /* * Generate HTTP redirect response with 302 status code and Location header. */ const response = { status: '302', statusDescription: 'Found', headers: { location: [{ key: 'Location', value: 'http://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html', }], }, }; callback(null, response); };

为 Lambda@Edge 编辑 Lambda 函数

当您要编辑 Lambda 函数时,请注意以下几点:

  • 原始版本标记为 $LATEST。

  • 您只能编辑 $LATEST 版本。

  • 每次编辑 $LATEST 版本时,均必须发布带编号的新版本。

  • 您无法为 $LATEST 创建触发器。

  • 当您发布函数的新版本时,Lambda 不会将触发器从以前的版本自动复制到新版本中。您必须为新版本重现触发器。

  • 当您将 CloudFront 事件的触发器添加到函数中时,如果已经有一个针对相同分配、缓存行为和同一函数早期版本的事件的触发器,则 Lambda 会从早期版本中删除该触发器。

编辑 Lambda 函数 (AWS Lambda 控制台)

  1. 通过以下网址登录 AWS 管理控制台并打开 AWS Lambda 控制台:https://console.amazonaws.cn/lambda/

  2. 在页面顶部的区域列表中,选择 美国东部(弗吉尼亚北部)

  3. 在函数列表中,选择您要编辑的函数的名称。

    默认情况下,控制台会显示 $LATEST 版本。您可以查看早期版本 (选择 Qualifiers),但是只能编辑 $LATEST。

  4. Code 选项卡上,对于 Code entry type,选择在浏览器中编辑代码、上传 .zip 文件,或从 Amazon S3 上传文件。

  5. 选择 SaveSave and test

  6. 选择 Actions,然后选择 Publish new version

  7. Publish new version from $LATEST 对话框中,输入新版本的描述。此描述会与自动生成的版本号一起显示在版本列表中。

  8. 选择 Publish

    新版本将自动成为最新版本。版本号会显示在页面左上角的 Version 按钮上。

  9. 选择 Triggers 选项卡。

  10. 选择 Add trigger

  11. Add trigger 对话框中,选择虚线框,然后再选择 CloudFront

    注意

    如果您已为函数创建一个或多个触发器,则 CloudFront 为默认服务。

  12. 指定以下值,以指示您希望 Lambda 函数何时执行。

    分配 ID

    选择要向其中添加触发器的分配的 ID。

    Cache behavior

    选择缓存行为,该行为将指定您要对其执行函数的对象。

    CloudFront event

    选择促使函数执行的 CloudFront 事件。

    Enable trigger and replicate

    选中此复选框,以便 Lambda 将函数复制到全球各地的区域。

  13. 选择 Submit

  14. 要为此函数添加更多触发器,请重复步骤 10 到 13。

测试和调试

您可在 Lambda 控制台上测试 Lambda@Edge 函数,并根据 CloudFront 事件对测试事件建模。然而,控制台中的测试只会验证逻辑,并不会应用特定于 Lambda@Edge 的服务限制。

您可以针对 Lambda@Edge 上运行的 Lambda 函数创建日志记录语句,并写入 CloudWatch Logs。有关更多信息,请参阅 CloudWatch 指标和 CloudWatch Logs 的 Lambda 函数

有关更多信息,请参阅 Amazon CloudFront 开发人员指南 中的以下主题:

Lambda@Edge 限制

由于执行环境受限,除了默认的 Lambda 限制之外,Lambda@Edge 还有其他限制。 有关更多信息,请参阅以下文档: