【问题标题】:AWS Lambda async code executionAWS Lambda 异步代码执行
【发布时间】:2019-01-28 07:38:21
【问题描述】:

我已经搜索过任何答案,但我读到的所有内容都是关于并发 lambda 执行和 Node 中的 async 关键字语法,但是我找不到关于 lambda 实例执行的信息。

这是因为我在一次聚会上,有人提到 lambda 实例(即由 AWS 托管的包含我的代码的临时容器)一次只能执行一个请求。这意味着,如果我有 5 个请求进来(为了简单起见,让我们说一个已经很温暖的实例)它们都将在一个单独的实例中运行,即在 5 个单独的容器中。

对我来说,香蕉的事情是,这破坏了异步编程多年的发展。从 2009 年开始,node.js 普及了 i/o 编程,考虑到对于磨机 CRUD 应用程序的无聊运行,您的大部分请求时间都花在等待外部数据库调用或其他东西上。编写异步代码允许单个执行线程看似执行许多同时请求。虽然 node 没有发明它,但我认为可以公平地说它普及了它,并且在过去十年中一直是后端技术发展的巨大推动力。许多语言添加了使异步编程更容易的功能(回调/任务/承诺/未来或任何您想调用的语言),并且 Web 服务器已从每个请求的单个线程转移到基于事件循环(节点、顶点、红隼等)往年的模型。

无论如何,历史课已经足够了,我的观点是,如果我所听到的是真的,那么使用 lambdas 开发将把大部分内容抛到窗外。如果 lambda 运行时永远不会通过我正在运行的实例发送多个请求,那么以异步方式编程只会浪费资源。例如,我在说 C#,而我的 lambda 用于检索小部件。那么这段代码var response = await db.GetWidgets() 实际上效率很低,因为它将当前线程上下文推入堆栈,因此它可以允许其他代码在等待该调用返回时执行。由于在原始请求完成之前不会调用其他请求,因此以同步方式编程更有意义,除了可以进行并行调用的地方。

这是正确的吗?

如果是这样,我真的很震惊,它没有被更多地讨论。我在过去几年中看到了异步编程的范式转变,这完全改变了这一点。

TL;DR:lambda 真的只允许每个实例一次执行一个请求吗?如果是这样,这将结束服务器开发向异步代码的重大转变。

【问题讨论】:

  • 如答案所示,所有 lambda 运行时一次只能处理一次执行。但是,使用自定义运行时,您可以通过在第一次执行完成之前再次调用下一次调用 API 来同时处理多个请求。我很想知道这是否有效。 docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html

标签: amazon-web-services asynchronous concurrency aws-lambda


【解决方案1】:

the above answer外,请参阅here。据我了解,这是一个同步循环。因此,从请求处理的角度来看,使事情异步的唯一方法是将工作委托给消息队列,例如SQS,如 here 所写。我认为这类似于 Celery 用于使 Django 异步的方式。最后,如果你真的想要在 node.js/python/c#/c++ 中按照async/await 异步处理请求,你可能需要使用 AWS Fargate / EC2 而不是 Lambda。否则,在 Lambda 中,正如您自己提到的那样,它确实是香蕉。另一方面,对于大流量,async/await 显示了它的好处,Lambda 不是一个很好的选择。 here 对 ec2、Lambda 和 Fargate 这三种服务进行了盈亏平衡分析。

【讨论】:

    【解决方案2】:

    你的问题是:

    由于在原始请求完成之前不会调用其他请求,因此以同步样式进行编程更有意义,除了可以进行并行调用的地方。

    否,因为您不再需要像使用同步进程时那样等待答案。您的触发器本身必须在调用后终止,以便释放内存。 Lamba 发送通知或在完成后触发新服务,或者观察者查看结果值(可以使用同步 lambda 等待答案,但由于 lambda 下的底层异步过程,它不准确系统本身)。作为一名 Android 开发人员,您可以将其与意图和广播进行比较,它是完全异步的。

    这是一种完全不同的解决方案设计方式,因为异步机制必须在工作流层本身进行管理,而不是在应用程序的核心,解决方案变成了触发微服务的通知器/观察器的聚合,它不再是数千行代码的单个二进制文件。

    每个 lambda 函数必须是一个单独的微服务。

    回来处理大流量,你可以并行运行数百万个 Lambda,只要你的微服务快速结束,它不会花费太多。 为确保您的工作流程不会丢失任何内容,您可以在解决方案中添加 SQS(队列消息传递)。

    【讨论】:

    • 我不确定我明白你在说什么。我说的是在 lambda 中执行的代码,而不是系统架构。当我说“异步”时,我指的不是带有消息队列等的异步系统。我说的是语言中的异步编程特性,想想async/await。该功能起作用的等待是将执行上下文(堆栈等)的任何内容转储到内存中并允许另一个线程运行。但是,由于 lamdba 不会为您提供任何其他线程来处理上下文切换,因此会影响性能。
    • 我以为您说的是单体应用程序。从 lambda 本身来看,在 lambda 函数中使用 async 对于成本模型也是一个坏主意。你必须尽快退出。
    • 这对我来说似乎很奇怪。我们多年来一直在告诉开发人员考虑 I/O 并编写异步代码,而这个模型将其抛弃。似乎没有任何理由,可以编写一个负载均衡器来允许 lambda 实例处理多个请求。
    • 继续思考 I/O 和异步约束至关重要,但您设计的解决方案具有这些约束,比 lambda 函数本身高出一步。
    【解决方案3】:

    是的,您是对的 - 即使您的 Lambda 异步执行某些工作,Lambda 也会启动多个容器来处理并发请求(我已经通过自己的经验证实了这一点,并且许多其他人也观察到了相同的行为 - 请参阅 @987654321 @到一个类似的问题)。这适用于每个受支持的运行时(C#、Node.js 等)。

    这意味着您的 Lambda 函数中的异步代码不允许一个 Lambda 容器同时处理多个请求,正如您所说。话虽如此,您仍然可以获得异步代码的所有其他好处,并且您仍然可以通过例如异步进行许多 Web 服务或数据库调用来潜在地提高 Lambda 的性能 - 所以 Lambda 的这个属性确实不 使异步编程在平台上无用。

    【讨论】:

      猜你喜欢
      • 2016-05-01
      • 2019-04-04
      • 2017-09-25
      • 2020-05-30
      • 2021-02-17
      • 1970-01-01
      • 2018-01-25
      • 1970-01-01
      相关资源
      最近更新 更多