【问题标题】:How to keep desired amount of AWS Lambda function containers warm如何保持所需数量的 AWS Lambda 函数容器温暖
【发布时间】:2018-12-15 01:34:37
【问题描述】:

在我的项目中,有在 AWS API Gateway 和 AWS Lambda 上实施的 REST API。由于 AWS Lambda 函数在我们调用它时是无服务器且无状态的,因此 AWS 使用处理我们调用的 Lambda 函数代码启动一个容器。根据AWS documentation,在 lambda 函数执行完成后,AWS 不会停止容器,我们可以在该容器中处理下一个调用。这种方法提高了服务的性能 - 只有在第一次调用 AWS 时才花时间启动容器(Lambda 函数的冷启动),并且所有下一次调用的执行速度更快,因为它们使用相同的容器(热启动)。

作为提高性能的下一步,我们创建了 cron 作业,它定期调用我们的 Lambda 函数(为此我们使用 Cloudwatch 规则)。这种方法允许保持 Lambda 函数“温暖”,从而避免容器的停止和重新启动。 IE。当真正的用户调用我们的 REST API 时,Lambda 不会花时间去启动一个新的容器。

但是我们遇到了这个问题 - 这种方法只允许保温一个 Lambda 函数容器,而来自不同用户的实际并行调用数量可能要大得多(在我们的例子中是数百个,有时甚至是数千个用户)。有没有办法为 Lambda 函数实现预热功能,不仅可以加热单个容器,还可以加热一些所需数量的容器?

我知道这种方法会影响 Lambda 函数的使用成本,并且可能使用好的旧应用程序服务器会更好,但我认为下一步将是比较这些方法及其成本,并且在当前时刻,我只想找到方法来加热所需的 Lambda 函数容器数量。

【问题讨论】:

  • 不幸的是,没有太多关于这个主题的文档。如果我们相信 AWS Docs,AWS Lambda 容器每个容器一次只能处理一个事件(如果我误解了,请纠正我)。如果你有一个单一的 cron lambda 函数,它同时向你的 API Lambda 函数发送 6 个事件,我猜它会到达 6 个不同的 lambda 容器。如果您认为值得一试,请告诉我您的发现。
  • @TomNijs 你是对的。单个容器永远不会处理多个并发调用。
  • 您是否检查过您实际获得了多少冷启动?如果您通常会同时调用 API,则应该同时有多个“暖”容器。
  • @GlebKosteiko 都是正确的;这是一个术语问题:容器经常被重用,但“重用”并不意味着函数的多个调用同时(同时)在给定容器中运行。如果,为了说明,你有一个需要 15 秒的函数,你现在和一分钟后调用它(没有其他东西在调用它),那么它很可能两次都在同一个容器中运行。但是如果你在 5 秒后一次又一次地运行它,这两个调用将永远不会在同一个容器中。重用不重叠。
  • 在问题的边缘,你使用什么语言,你分配了多少内存?有些语言的启动速度比其他语言慢得多(Java),所以如果您愿意为一些改进的性能付出代价,您有时可以通过增加内存来减少冷启动时间,因为这会将可用的 CPU 周期增加大致相同的因素。 . 例如从 128MB 更改为 512MB 也意味着获得 4 倍的 CPU 量,即使您实际上并不需要更多内存,而且增加的内存不会直接改变性能。如果不需要,不使用 VPC 也有帮助。

标签: performance amazon-web-services aws-lambda amazon-cloudwatch cold-start


【解决方案1】:

这可能会很长,但请耐心等待,因为这可能会为您提供解决方法,并且可能会让您更好地理解 Lambda 的工作原理?

如果您对阅读不感兴趣,您也可以跳到底部解决方法”。

对于不了解冷启动的人,请阅读this blog 帖子以更好地理解它。简而言之:

冷启动

  • 第一次执行函数时或 功能代码或资源配置更新,容器将 旋转起来执行这个功能。所有的代码和库都将 加载到容器中以使其能够执行。该代码将 然后运行,从初始化代码开始。初始化 code 是在处理程序之外编写的代码。此代码仅运行 第一次创建容器时。最后,拉姆达 处理程序被执行。 这个设置过程被认为是感冒 开始。
  • 为了提高性能,Lambda 能够重用创建的容器 通过以前的调用。这将避免初始化一个新的 容器和代码加载。只有处理程序代码将是 执行。但是,您不能依赖以前的容器 要重用的调用。如果您没有更改代码,也没有更改 时间过去了,Lambda 可能会重复使用之前的容器。
  • 如果更改了代码、资源配置或某段时间 自上次调用以来通过,一个新的容器将是 初始化,您将经历冷启动。

现在考虑这些场景以便更好地理解:

  • 考虑第一次调用示例中的 Lambda 函数。 Lambda 将创建一个容器,将代码加载到容器中并运行初始化代码。然后将执行函数处理程序。此调用将经历冷启动。如 cmets 中所述,该功能需要 15 秒才能完成。一分钟后,再次调用该函数。 Lambda 很可能会重新使用上一次调用中的容器。此调用不会经历冷启动。
  • 现在考虑第二种情况,第二次调用在第一次调用后 5 秒执行。由于前一个函数需要 15 秒才能完成并且尚未完成执行,因此新的调用必须创建一个新容器才能执行此函数。因此此调用将经历冷启动。

现在提出您已解决的问题的第一部分:

关于防止冷启动,这是一种可能性,但不能保证,常见的解决方法只会保温 Lambda 函数的一个容器。为此,您将使用计划事件(cron 表达式)运行 CloudWatch 事件,该事件将每隔几分钟调用一次您的 Lambda 函数以使其保持温暖。


解决方法:

对于您的用例,您的 Lambda 函数将非常频繁地调用,并具有非常高的并发率。为避免尽可能多的冷启动,您将需要保持尽可能多的容器,以达到您期望的最高并发性。为此,您将需要延迟调用函数以允许此函数的并发性构建并达到所需的并发执行量。这将迫使 Lambda 增加您想要的容器数量。因此,这可能会增加成本,并且不能保证避免冷启动。

话虽如此,下面是关于如何同时为您的函数保持多个容器温暖的分解:

  • 您应该有一个按计划触发的 CloudWatch 事件规则。此计划可以是固定速率或 cron 表达式。例如,您可以将此规则设置为每 5 分钟触发一次。您将然后指定一个 Lambda 函数(控制器函数)作为此规则的目标。

  • 然后,您的 Controller Lambda 函数为尽可能多的并发运行的容器调用 Lambda 函数(您想要保温的函数)。

这里有几点需要考虑:

  1. 您必须构建并发,因为如果第一次调用 在另一个调用开始之前完成然后这个调用 可以重用以前的调用容器,而不是创建一个新的 一。为此,您需要在 控制器调用的 Lambda 函数 功能。 这可以通过将特定的有效负载传递给 带有这些调用的函数。你的 lambda 函数 想要保持温暖将检查此有效负载是否存在。如果 它确实然后该函数将等待(构建并发 调用),如果没有,则函数可以执行为 预期。

  2. 您还需要确保在重复调用 Invoke Lambda API 调用时不会受到限制。您的 拉姆达 如果发生这种限制,应该编写函数来处理这种限制 并考虑在 API 调用之间添加延迟以避免限制。

最后,此解决方案可以减少冷启动,但会增加成本,并且不能保证会发生冷启动,因为在使用 Lambda 时它们是不可避免的。如果您的应用程序需要更快的响应时间,那么使用Lambda 冷启动,我建议您将服务器放在 EC2 实例上。

【讨论】:

    【解决方案2】:

    我们正在使用 java (spring boot) lambdas,并得出了与上面 Kush Vyas 的答案几乎相同的解决方案,效果非常好。

    我们确实在负载测试期间发现,在“控制器功能”执行期间经常会出现合法的用户请求,再次导致不可避免的冷启动......

    所以,现在在我们的“控制器函数”中,我们有常规数量的 X 个并发预热请求,但是每执行 5 次函数,我们就会额外调用 2 次目标 lambda。理论上,我们最终会得到 X+2 个 lambdas 来保持温暖,但对于 5 个预热调用中的 4 个,仍然会有 2 个冗余 lambdas 可以服务用户请求。

    它确实进一步减少了我们的冷启动次数(但显然仍不完全),我们仍在使用并发/热身频率/睡眠时间组合来为我们找到最佳解决方案 - 这些值总是很可能取决于特定情况的负载要求。

    【讨论】:

      【解决方案3】:

      AWS 刚刚宣布:

      https://aws.amazon.com/about-aws/whats-new/2019/12/aws-lambda-announces-provisioned-concurrency/

      请注意,虽然它不是免费的,而且对于我们保持 10 个 lambda 实例温暖的简单用例,我们的每日成本似乎会从 0.06 美元增加到 4 美元

      【讨论】:

        【解决方案4】:

        如果您将 serverless framework 与 AWS Lambda 一起使用,则可以使用此 plugin 来保持所有 lambdas 温暖并具有一定的并发性。

        【讨论】:

          【解决方案5】:

          我想分享一些小而有用的技巧,我们用它来减少与冷启动相关的“用户观察到”延迟。在我们的例子中,Lambda 函数通过 AWS API Gateway 处理来自前端的 HTTP 请求,特别是当用户在输入字段中键入内容时执行搜索功能。通常用户在 UI 渲染后开始输入会有一些延迟,所以我们有一些时间来执行对 Lambda 函数的 ping 调用以预热它。当用户向后端发出请求时,Lambda 很可能已经准备好工作了。

          实际上,这种方法对于解决后端冷启动问题没有任何作用,您需要寻找其他选项来解决它,但它可以在不费力气的情况下改善用户体验(类似于 hotfix )。

          您应该记住的一件事 - 如果您的服务是公开的并且您关心 Google Insights 得分,那么您应该谨慎实施这种方法。

          【讨论】:

            猜你喜欢
            • 2017-08-10
            • 2017-09-26
            • 2019-09-03
            • 2019-01-17
            • 1970-01-01
            • 2018-11-29
            • 2017-11-29
            • 1970-01-01
            相关资源
            最近更新 更多