预置并发无法解决冷启动问题

Ron*_*rty 8 aws-lambda

我有一个 lambda 函数,它在生产中很少被调用,但它是面向公众的,所以我想避免冷启动。所以我想我可以使用预配置的并发来避免这个问题。我的 Cloudformation 模板如下所示:

QuoteLinkServiceFunction:
    Type: AWS::Serverless::Function
    Properties:
      # other lambda properties...
      ProvisionedConcurrencyConfig:
        ProvisionedConcurrentExecutions: 1
Run Code Online (Sandbox Code Playgroud)

当我在我的测试环境中创建这个堆栈时(我是唯一的用户,所以没有其他调用同时发生),当我在几个小时后返回使用这个函数时仍然会遇到冷启动。由于 lambda 现在已预热,因此在第一次调用之后立即进行的后续调用会运行得更快。

lambda 控制台显示此函数的别名实际上已设置为预配并发为 1,并且我已验证 ALB 目标组指向别名。那么为什么我仍然冷启动?

Mar*_*Roy 18

长话短说:


我们遇到了同样的问题,但尚未找到任何解决方法。最后,Lambda 实例是暂时的,因此无法保证连续正常运行时间(即使具有预配置的并发性)。

预置并发确实为您提供了许多正在运行的实例的保证 - 尽管这些实例可以在任何时间点与其他实例交换(并且在发生这种情况时会导致冷启动)。交换的频率似乎相当随意,我认为完全取决于 AWS。

编辑:我们最终意识到这根本不是问题!它只与预配置并发功能的本质有关:

  • 通过预配置并发,初始化/冷启动仍然会发生,但它们发生在Lambda 可供调用之前。

    • 当将预配置并发设置为 1 并查看日志时,您可以看出这种情况 - 新实例将在前一个实例仍在被调用的同时被初始化,然后新实例将在前一个实例被丢弃时开始被调用。
    • 这实际上意味着客户不会经历这些冷启动!它只是在后台发生。
  • 然而,如果 lambda 函数没有很好地利用静态初始化,客户端仍然可能会遇到另一种形式的冷启动——静态初始化通常比 Lambda 初始化本身慢:

在我们对跨生产调用的 Lambda 性能的分析中,数据显示函数执行前延迟的最大贡献者来自 INIT 代码。

下面的图片(来自Lambda 性能优化指南)很好地总结了所有这些。

  • 前两个没有配置并发:

无预配置并发的冷启动

无预配置并发的冷启动

  • 另外两个启用了预配置并发:

冷启动并配置并发

冷启动并配置并发


判断 Lambda 是否确实进行冷启动的一个好方法是查看 CloudWatch 中的日志。每个请求都应该有一个REPORT如下所示的日志:

REPORT RequestId: f840a316-cf35-42ec-8f4d-c03a6cde9192  Duration: 368.80 ms Billed Duration: 369 ms Memory Size: 128 MB Max Memory Used: 93 MB  Init Duration: 3569.10 ms
Run Code Online (Sandbox Code Playgroud)

如果你看到Init Duration日志末尾,那么确实是冷启动。然而,对于预配置的并发性,此初始化持续时间发生在调用 Lambda之前。

此外,每次 AWS 启动新的 Lambda“实例”时,似乎都会创建一个新的 CloudWatch 日志流 - 这会导致冷启动,每个日志流的第一个请求都有一个Init Duration. 因此,只需查看“首次事件时间”列即可显示所有冷启动(可以通过首选项/齿轮图标添加该列)。

这在Lambda 性能优化指南中得到了进一步证实:

初始化代码的运行频率高于调用总数。由于 Lambda 具有高可用性,因此对于每一个预置并发单元,至少在不同的可用区中准备两个执行环境。这是为了确保您的代码在服务中断时可用。随着环境的收获和负载平衡的发生,Lambda 会过度配置环境以确保可用性。您无需为此活动付费。如果您的代码初始值设定项实现了日志记录,则即使未调用主处理程序,您也会在运行此代码时随时看到其他日志文件。


查看日志也是一个好主意START,以确保正在调用预期版本(配置了预配并发的版本):

START RequestId: f840a316-cf35-42ec-8f4d-c03a6cde9192   Version: 15
Run Code Online (Sandbox Code Playgroud)

确保版本不是$LATEST无法从预配置并发中受益)尤其重要:

函数的每个版本只能有一个预配置的并发配置。这可以直接位于版本本身上,也可以位于指向该版本的别名上。两个别名无法为同一版本分配预配置并发。此外,您无法在指向未发布版本 ($LATEST) 的别名上分配预配置并发。


BAD*_*EED 2

您确定这些确实是冷启动延迟而不是数据库连接问题吗?您是否考虑过使用 X-Ray 进行追踪?您可以将要测量的指令包装在一个段内。

这是一个示例应用程序。