【问题标题】:How does AWS Lambda serve multiple requests?AWS Lambda 如何处理多个请求?
【发布时间】:2018-01-28 13:32:45
【问题描述】:

AWS Lambda 如何处理多个请求? 我想知道这里也是多线程模型吗?

如果我从 API 网关调用 Lambda。 API 在 10 秒内有 1000 个请求。将创建多少个容器以及多少个线程。

【问题讨论】:

  • 您的具体用例是什么?你的问题太模糊了。
  • 对于不同的用例,并发单位也不同(对于像 Kinesis 这样的基于流的侦听器,它的分片数量和非基于流的,它基于事件 - 创建的 DDB 项目数/S3 文档已推送/AWS API 调用。docs.aws.amazon.com/lambda/latest/dg/concurrent-executions.html
  • 如果我从 API 网关调用 Lambda。 API 在 10 秒内有 1000 个请求。将创建多少个容器以及多少个线程。
  • 1000 个默认 IIRC 容器同时执行,每次执行都是单线程的。并行性位于容器级别的不同抽象层上(考虑不同的主机或基于 impl 的 docker 容器),而不是操作系统级别的线程。在客户端层,这个实现细节应该没有任何意义。当然,如果您在每个调用层都需要并行性,则必须以这种方式编写应用程序(例如,node js 运行时将允许您生成大量异步内容)。

标签: java aws-lambda


【解决方案1】:

AWS Lambda 如何处理多个请求?

独立。

我想知道这里也是多线程模型吗?

不,它不是您所要求的意义上的多线程模型

当然,您的代码可以编写为使用多个线程和/或子进程来完成它打算完成的任何目的一次调用,但 Lambda 不会发送多个一次调用同一个容器。在第一次调用完成之前,该容器不会用于第二次调用。如果第二个请求在第一个请求运行时到达,第二个请求将在不同的容器中运行。

如果我从 API 网关调用 Lambda。 API 在 10 秒内有 1000 个请求。将创建多少个容器和多少个线程?

将根据需要创建尽可能多的容器,以在其自己的容器中处理每个到达的请求。

每次调用的持续时间将是最大的决定因素。

10 秒内 1000 个非常快的请求大致相当于 1 秒内 100 个请求。假设每个请求在不到 1 秒的时间内完成并且到达时间是均匀分布的,您可以预期创建的容器少于 100 个。

另一方面,如果 1000 个请求在 10 秒内到达,每个请求需要 30 秒才能完成,那么在此事件期间您将有 1000 个容器存在。

在流量激增导致容器数量膨胀后,它们都会停留几分钟,准备好处理额外负载(如果到达),然后 Lambda 将开始终止它们。

【讨论】:

【解决方案2】:

AWS Lambda 能够通过水平扩展多个容器来服务多个请求。 Lambda 默认最多支持 1000 个parallel container executions

在 10 秒内向 API 发送了 1000 个请求。将创建多少个容器以及多少个线程。

每秒请求数 = 1000/10 = 100

假设每次执行需要 1 秒或更长时间才能完成,将有 100 次并行 Lambda 执行。

注意:您也可以生成多个线程,但很难预测性能提升。

另外请记住,拥有多个线程并不总是 高效 Lambda 函数可用的 CPU 在 您的 Lambda 函数创建的所有线程和进程。一般你 通过并行运行工作不会在 Lambda 函数中获得更多 CPU 在多个线程之间。在这种情况下,您的代码实际上并未运行 在两个内核上,但在单个内核上的两个“超线程”上;根据 工作量,这可能比单线程更好或更差。这 服务团队正在寻找更好地利用多个核心的方法 Lambda 执行环境,我们会将您的反馈作为 为该功能 +1。

参考:AWS Forum Post

有关 Lambda 并发执行的更多详细信息,请参阅 this aws 文档。

【讨论】:

  • “注意:默认情况下,Lambda 最多可以支持 1000 个(进程和线程的总和)并发执行。” 这是不正确的。在这里,进程和线程不是一个因素。 1000 个并发调用意味着 1000 个容器。每个调用都完全独立于任何其他调用。您在代码中使用进程和线程执行的任何操作都适用于 一个 调用——而不是跨它们。
  • @Michael 感谢您的意见。我也有同样的感觉,但是在进一步阅读文档时,我在 aws doc 中找到了信息。 docs.aws.amazon.com/lambda/latest/dg/limits.html是错字还是我的解释有误?
  • 您在解释中结合了两个不相关的概念。请注意表格的标题:AWS Lambda Resource Limits per Invocation。这是线程和进程在一个 Lambda 调用中的限制。并发调用不相互交互。它们中的每一个都可以独立地创建多达 1024 个线程/进程(很少有你需要的东西),它们每个都有 512M 的临时空间,它们每个都有你配置的内存量,并且它们不与每个竞争其他用于 CPU 周期。并发调用限制是一个类似的数字,只是巧合。
  • 感谢@Michael 同意您的观点并相应地更新了答案以供将来参考。
  • 另一个细微差别是“突发并发配额”——根据您所在的 AWS 区域,您将受限于可以预置的新实例数量。在此配额之前,AWS 将立即预置新实例,但超出此配额后,新实例将以每分钟 500 个实例的速度创建,超出的请求会收到 429 个异常。 docs.aws.amazon.com/lambda/latest/dg/invocation-scaling.html
【解决方案3】:

有几个角度可以讨论。

AWS Lambda 确实支持并行处理请求,但 Lambda 的任何单个实例/容器一次只能处理一个请求。如果所有现有实例都忙,则将配置新实例(取决于并发设置,如下所述)。

在单个 Lambda 实例中支持多线程,但每个实例仍只能处理一个请求。实际上,并行化在 Lambda 中很少有好处,它会增加大量开销,并且最适合用于处理非常大的集合。此外,Lambda 需要拥有超过 1 个虚拟内核才能获得任何好处。核心是通过提高内存设置来配置的——许多 Lambda 以足够低的内存设置运行,只有一个核心。

由于有很多因素,并不总是能够准确确定创建了多少容器/实例:

  • Lambda 将重用任何现有的、暂停的实例
  • 现有实例处理请求的速度通常非常快,少量暖实例可以在配置新实例所需的时间内处理大量请求(尤其是对于像 Java 或 .NET Core 这样的运行时,它们通常有启动时间1 秒以上)
  • Lambda 的并发设置是一个重要因素
    • 如果您有 X 的预留并发,您将永远不会拥有超过 X 个实例
    • 如果您有未保留的并发,则限制基于可用的并发。这默认为每个账户 1000 个实例,因此如果任何 Lambda 的 990 个实例已经存在,那么只能创建 10 个
    • 如果您已配置并发,那么您将始终拥有最少数量的实例,从而减少冷启动

但是,为了尝试回答您的故事问题,我们假设您在 10 分钟内以稳定的速度发送 1000 个请求。这是每 600 毫秒一个请求。我们还假设您的 Java 应用程序分配了相当高的内存,并且它的初始化相对较快——假设冷启动需要 1 秒。冷启动完成后,调用速度很快——比如说 10 毫秒。而且,让我们假设流量开始时没有实例。

第一个请求的响应时间约为 1,010 毫秒——冷启动需要 1 秒,处理请求需要 10 毫秒。第二个请求将在第一个请求仍在处理时到达,因此 Lambda 很可能会提供第二个实例,并且第二个请求将看到类似的响应时间。

到第三个请求到来时(启动后 1800 毫秒),两个实例现在都处于空闲状态并且可以重用——因此该请求不会经历冷启动,响应时间将为 10 毫秒。从现在开始,很可能不需要额外的实例——但这一切都假设请求率稳定。

但是——改变任何变量都会产生很大的影响。

【讨论】:

    猜你喜欢
    • 2022-06-16
    • 2019-02-28
    • 1970-01-01
    • 1970-01-01
    • 2020-06-27
    • 2023-01-02
    • 1970-01-01
    • 2018-08-19
    • 2013-01-12
    相关资源
    最近更新 更多