当异步调用Lambda时,不用实时等待Lambda返回结果。一些AWS服务,例如S3、SNS,会使用异步调用Lambda的方式来对事件进行处理。
异步调用
方式由于对调用者立即返回结果,所以不会让调用者等待而造成负担。例如同时往S3上传了10万个文件, 假设S3 Event调用Lambda时采用同步调用
的方式,那么S3必须等待这1万个文件处理完成,这会对S3后端将造成很大负担
下面的图展示了异步调用Lambda的原理——当事件触发时,Lambda将事件信息保存到内部队列(Event Queue)里,再进行后续的处理:
在上一节,我们使用了同步调用方式来运行hello-world
:
aws lambda invoke --function-name hello-world response.json
使用--invocation-type Event
参数,可以将Lambda执行方式变成异步调用
:
aws lambda invoke --function-name hello-world --invocation-type Event response.json
观察到命令行立刻返回结果: StatusCode 202
,sleep 5秒的逻辑在后台会继续运行,在命令行不会得到后续程序处理的结果数据。
和同步调用方式相比,异步调用时Lambda增加了自动错误处理机制,当代码执行出错时:
Dead Letter Queue
,收集执行Lambda失败时的相关信息上面的特性将在下面的实验中展现的淋漓尽致
将hello-world
代码更新为:
import json
import time
def lambda_handler(event, context):
# TODO implement
print("hello world")
raise Exception('Something wrong in the backend')
由于主动抛出异常——raise Exception
,上面的代码运行后将触发错误,用于触发Lambda异步调用时错误处理的机制。
在Cloud 9中调用hello-world函数:
耐心等待三分钟,到CloudWatch Log中查看Lambda最新的日志流:
我们只调用了一次Lambda,但在后台能够看到有三次执行(1次调用执行 + 2次retry)。且第二次执行在间隔1min后,第三次执行在间隔2min后。
虽然Lambda保证了自动重试,但假设我们的程序执行了三次后依然失败,还是需要将信息收集到死信队列(dead letter queue), 用于分析出错原因或者触发后续的处理机制。
进入SQS页面,创建SQS,用于作为Lambda的死信队列:
点击创建。
由于Lambda需要将死信发送到SQS,所以Lambda要有访问SQS的权限。为Lambda的Role添加权限:
添加AmazonSQSFullAccess
权限,这样Lambda具有访问SQS的能力:
编辑Lambda异步调用的相关配置:
将Dead-letter queue设置为刚才我们创建的SQS,并保存:
重新执行两条测试,在第二条测试时,传入event数据(第一条测试的event数据实际为{}
):
aws lambda invoke --function-name hello-world --invocation-type Event response.json
aws lambda invoke --function-name hello-world --invocation-type Event --cli-binary-format raw-in-base64-out --payload '{"key-test": "value-test"}' response.json
等待三分钟后,查看SQS,发现有两条新的消息:
查看消息内容:
上面两次执行Lambda都失败,得到两条死信消息:
在执行Lambda失败后,传入的Event数据会被记录到死信列队里: