AWS Lambda 的调用方式简介
这篇文章简单聊下 AWS Lambda 的调用方式。
同步和异步
Lambda 有两种调用方式:同步和异步。
- 同步调用,Lambda 函数会在运行完成后直接返回结果。
- 异步调用,Lambda 函数会将调用信息加入队列,并在执行完成后将结果作为参数传输给指定的目标。
同步调用非常直观,就如我们调用一个普通函数一样,这里不细说。主要说下异步调用。
异步调用
异步调用 Lambda 函数时,Lambda 服务会立刻返回
202 Accepted
代码并将函数调用信息置入 Lambda 调用队列。
Lambda 服务的异步执行者会从不断这个队列中取出调用信息并执行。如果函数返回错误,则 Lambda 服务会自动重试 2 次。
如果 Lambda 达到并发上限,则异步执行者会把调用信息重新置入队列,并在 6 小时内不断重试。
注意:队列本身是「最终一致」的,意味着同一个调用有可能被执行多次。
异步调用目标
异步调用完成后,Lambda 会将结果发送给制定的目标。支持的目标有:
- Amazon SQS 队列
- Amazon SNS 主题
- Amazon Lambda,作为另一个 Lambda 函数的输入
- Amazon EventBridge,作为一个时间发送到事件总线
也可以配置「死信队列」(dead-letter queue),用于接收发送失败的调用。
此异步非彼异步
很多编程语言运行时也提供「异步」机制,但是语言的异步,和 Lambda 的异步调用 完全是两件事情 。
编程语言运行时提供的异步机制,通常是指编程语言使用额外的线程来执行某个函数,并在主线程利用类似无限循环的机制, 等待 这些线程执行结束,再返回结果。
比如说,在 NodeJS 中,我们可能使用 AWS SDK 来调用 S3 的
ListObject
API。这是一个
async
函数,即异步函数,我们需要用
await
来获取它的执行结果。
在
await
的过程中,Lambda 函数仍然处于激活状态。
await
需要多久,Lambda 函数就会执行并计费多久。NodeJS 的运行环境会等待所有的
await
都完成(即所有
Promise
都
resolve
)之后,再返回并重新进入「可调用状态」。
由此可知,使用编程语言的异步机制并不会让函数在「后台」执行,也无法缩短 Lambda 的执行时间。
编程语言异步的正确用法
在 Lambda 语境下,我们应该把编程语言的异步视作是一种多线程机制而不是异步机制。
如果我们需要执行多个任务,它们相互之间没有依赖关系,就可以使用编程语言的异步机制。比如,我们需要更新 A 数据库,从 B 桶中拉取图片,再打日志到 C 服务,这些任务都相互不依赖。
如果线性执行这些任务,那么就会浪费大量的时间,而且计算资源也没有用满。这时候,我们就可以使用编程语言的异步机制,同时
async
调用 A、B、C,再分别
await
,这样就可以大大缩短执行时间。