如何保持所需数量的AWS Lambda函数容器温暖

时间:2018-07-06 12:25:12

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

在我的项目中,有一个在AWS API Gateway和AWS Lambda上实现的REST API。由于AWS Lambda函数在我们对其进行调用时是无服务器且无状态的,因此AWS使用Lambda函数的代码启动一个容器来处理我们的调用。根据{{​​3}},lambda函数执行完成后,AWS不会停止容器,而我们能够处理该容器中的下一个调用。这种方法提高了服务的性能-仅在首次调用时AWS才花时间启动容器(冷启动Lambda函数),并且所有下一个调用都使用相同的容器(热启动),因此执行速度更快。

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

但是我们面临一个问题-这种方法只允许保管一个Lambda函数容器,而来自不同用户的并行调用的实际数量可能更大(在我们的情况下,这是数百个,甚至数千个用户)。有什么方法可以实现Lambda函数的预热功能,它不仅可以预热单个容器,还可以预热一些容器?

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

5 个答案:

答案 0 :(得分:12)

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

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

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

冷启动

  • 首次执行功能或在执行完功能后 功能代码或资源配置已更新,容器将 旋转执行该功能。所有的代码和库将 加载到容器中以便能够执行。该代码将 然后从初始化代码开始运行。初始化 代码是在处理程序外部编写的代码。此代码仅运行 首次创建容器时。最后,Lambda 处理程序被执行。 此设置过程被称为“感冒” 开始。
  • 为了提高性能,Lambda可以重复使用创建的容器 通过以前的调用。这将避免初始化新的 容器和代码加载。只有处理程序代码是 被执行。但是,您不能依赖以前的容器 要重用的调用。如果您还没有更改代码,也不会 很多时间过去了,Lambda可能会重用以前的容器。
  • 如果您更改代码,资源配置或一段时间 自上次调用以来传递的新容器 初始化,您将体验到冷启动。

现在考虑以下情况以更好地理解:

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

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

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


解决方法:

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

话虽如此,这是关于如何一次为功能保持多个容器保暖的一种细分:

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

  • 您的 Controller Lambda函数随后将为任意数量的并发运行的容器调用Lambda函数(您希望保持温暖的函数)。

这里有几件事要考虑:

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

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

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

答案 1 :(得分:3)

我们正在使用java(春季启动)lambda,并且已经获得了与上述Kush Vyas答案完全相同的解决方案。

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

因此,现在在“控制器功能”中,我们有常规的X个并发预热请求,但是每执行第5次函数,我们就将目标Lambda额外调用2次。从理论上讲,我们最终将使X + 2 lambda保持温暖,但是对于5个热身电话中的4个,仍然会有2个冗余lambda可以满足用户请求。

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

答案 2 :(得分:1)

如果您将serverless framework与AWS Lambda一起使用,则可以使用此plugin来确保所有lambda保持一定的并发水平。

答案 3 :(得分:1)

AWS刚刚宣布了这一点:

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

请注意,虽然它不是免费的,并且对于保持10个lambda实例温暖的简单用例,看来我们的每日费用将从0.06美元增加到4美元

答案 4 :(得分:0)

我想分享一些小而有用的技巧,我们将其用于减少与冷启动相关的“用户观察到的”延迟。在我们的案例中,Lambda函数通过AWS API Gateway处理来自前端的HTTP请求,尤其是当用户在输入字段中键入内容时执行搜索功能。通常,用户界面呈现后,用户会开始输入一些延迟,因此我们有一些时间对我们的Lambda函数执行ping调用以对其进行预热。当用户向后端发出请求时,Lambda很可能已准备就绪。

实际上,这种方法无法解决后端冷启动的问题,您将需要寻找其他方法来解决此问题,但这可以为用户带来很多改进,而无需付出很多努力(例如修复程序) )。

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