代码之家  ›  专栏  ›  技术社区  ›  Hleb

如何使所需数量的aws lambda函数容器保持温暖

  •  9
  • Hleb  · 技术社区  · 7 年前

    在我的项目中有rest api,它在awsapi网关和aws lambda上实现。由于aws lambda函数是无服务器和无状态的,当我们调用它时,aws会用lambda函数的代码启动一个容器来处理我们的调用。根据 AWS documentation 完成lambda函数执行后,aws不会停止容器,我们可以处理该容器中的下一个调用。这种方法提高了服务的性能—只有在第一次调用时,aws才花时间启动容器(lambda函数的冷启动),而所有下一次调用都执行得更快,因为它们使用相同的容器(热启动)。

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

    但我们面临的问题是,这样的方法只允许让lambda函数的一个容器保持温暖,而来自不同用户的并行调用的实际数量可能要大得多(在我们的例子中,是成百上千的用户)。有没有什么方法可以实现lambda函数的预热功能,它不仅可以预热单个容器,还可以预热一些所需数量的容器?

    我知道这样的方法可能会影响lambda函数的使用成本,而且可能,使用好的旧应用服务器会更好,但是我认为,比较这些方法及其成本将是下一步,目前我只想找到一种方法来暖化lambda函数容器的期望计数。

    4 回复  |  直到 7 年前
        1
  •  14
  •   Jonathan Hall    7 年前

    这可能很长,但请容忍我,因为这可能会给你解决办法,可能会让你更好地理解 lambda是如何工作的?

    或者你可以 跳到底部 “。” 解决办法 “如果你对阅读不感兴趣。

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

    冷起动

    • 当函数第一次执行或在 函数代码或资源配置已更新,容器将 启动以执行此函数。所有的代码和库 装载到容器中以便执行。代码将 然后运行,从初始化代码开始。初始化 代码是在处理程序外部编写的代码。此代码只运行 第一次创建容器时。最后,兰姆达 处理程序已执行。 这种设置过程被认为是一种感冒 开始。
    • 为了提高性能,lambda可以重用创建的容器 通过以前的调用。这将避免初始化新的 集装箱和装载代码。只有处理程序代码 执行。但是,不能依赖于以前的容器 要重用的调用。如果你没有改变密码 很多时间过去了,lambda可能会重用以前的容器。
    • 如果更改代码、资源配置或 自上一次调用以来传递,新容器将 初始化后,您将体验冷启动。

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

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

    现在来谈谈你已经解决的问题的第一部分:

    关于防止冷启动,这是一种可能性,但是,它并不能保证,普通的解决方法将只保温一个容器的lambda功能。为此,您可以使用调度事件(cron表达式)运行一个cloudwatch事件,该事件将每隔几分钟调用lambda函数以保持其温暖。


    解决方法:

    对于您的用例,lambda函数将是 频繁调用 用一个 非常高的并发率 是的。为了避免尽可能多的冷启动,您将需要尽可能多的容器保持温暖,因为您希望达到最高并发。做这个你会的 需要延迟调用函数以允许此函数的并发性生成并达到所需的并发执行量 是的。这将迫使lambda增加所需的容器数量。因此,这会增加成本,并不能保证避免冷启动。

    这就是说,这里有一个关于如何让多个容器同时为您的功能保暖的分解:

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

    • 你的 控制器lambda函数 那么威尔 调用lambda函数(希望保持温暖的函数)以获得所需数量的并发运行容器。

    这里有几点需要考虑:

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

    2. 如果反复调用invoke lambda api调用,还需要确保不会受到限制。你的 兰姆达 如果发生此限制,则应编写函数来处理它 并考虑在api调用之间添加延迟以避免限制。

    最后,这个解决方案可以减少冷启动,但它会增加成本,并不能保证冷启动会发生,因为在使用lambda时不可避免。如果应用程序需要更快的响应时间,那么LAMBDA冷启动会发生什么,我建议您在EC2实例中查看您的服务器。

        2
  •  3
  •   Stuart Reavell    7 年前

    我们正在使用java(spring boot)lambdas,并且已经得到了与kush vyas的答案几乎相同的解决方案,上面的答案工作得非常好。

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

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

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

        3
  •  1
  •   skunkwerk    6 年前

    如果你使用 serverless framework 有了aws lambda,你可以使用这个 plugin 在一定的并发级别上保持所有lambda的温暖。

        4
  •  0
  •   Hleb    6 年前

    我想分享一些小而有用的技巧,我们用这些技巧来减少与冷启动相关的“用户观察到的”延迟。在我们的例子中,lambda函数通过aws api网关处理来自前端的http请求,特别是当用户在输入字段中键入某些内容时执行搜索功能。通常用户在呈现ui之后会有一些延迟开始输入,所以我们有一些时间来执行对lambda函数的ping调用来预热它。当用户向后端发出请求时,lambda很可能就可以工作了。

    事实上,这种方法在后端的冷启动上解决不了问题,你需要寻找其他选项来修复它,但是它可以是用户体验的改进而不需要太多的努力(比如热修复)。

    有一件事你应该记住——如果你的服务是公开的,而且你关心google insights的分数,那么你应该小心实施这种方法。