亚马逊AWS官方博客

使用 Provisioned Concurrency 创建低延迟、高容量 API

Original URL: https://amazonaws-china.com/cn/blogs/compute/creating-low-latency-high-volume-apis-with-provisioned-concurrency/

 

AWS Lambda服务可以响应事件,按需运行客户代码。它会创建新的执行环境,并下载相应代码。此项初始设置常被称为“冷启动”,且往往会延长函数的总执行时间。

当函数被首次调用,或者长时间未被使用时,会触发冷启动。另外,当Lambda扩展函数时,也会触发冷启动,这是因为函数内的每个新实例都是一个新的执行环境。

无服务器社区此前已经开发出多种“函数加热器”库(https://github.com/jeremydaly/lambda-warmer ),帮助提升利用现有环境调用Lambda函数的能力。对于开发及测试类工作负载,或者不需要超高性能的使用场景,这无疑是一种理想的解决方案。而Provisioned Concurrency功能,则负责支持那些要求延迟更低且更具可预测性的工作负载。

本文将介绍如何消除Web应用程序架构中的冷启动状况。在这里我们引用了Ask Around Me的示例应用代码,此应用主要帮助用户立足当前所在地理区域实时提出问题并获得解答。要了解更多详细信息,请参阅该应用程序系列博文的第一部分

冷启动与Web应用程序

Ask Around Me应用程序使用以下后端架构:

这是一类典型的Web应用程序架构。Amazon API Gateway调用部分Lambda函数,其余函数则由应用程序栈中的服务进行调用。API Gateway对Lambda函数采用同步调用方式,意味着除非该函数返回相应值,否则调用方将持续保持被阻塞状态。

由Amazon SQS与Amazon DynamoDB等服务调用的函数则采用异步调用。这意味着调用方将在调用过程中继续处理其他工作,且被调用的函数不会返回任何值。示例应用程序同样用到这两种调用类型:

通常,冷启动对异步执行的影响较小。在这类情况下,执行环境的启动等待时间往往不会给应用程序的整体性能造成明显拖累。而对于Web应用程序,冷启动造成的性能影响在前端同步应用程序中体现得最为明显,意味着API请求速度将给用户体验带来相当直接的影响。

在Ask Around Me当中,由四项Lambda函数支持应用程序的API端点。其中三项为轻量级函数,我们可以将消息放入SQS队列并从DynamoDB表中检索数据。其使用率也相对最高,预计每小时需要处理50000项查询,这也使其成为性能优化工作中的关注重点。

评估现有Lambda函数性能

在之前针对这款应用程序的负载测试博文当中,GetQuestions API显示该应用的性能表现存在巨大波动。在每秒20次请求、持续30秒的API负载测试中,平均响应延迟为175毫秒,但最高响应延迟却达到2149毫秒。

在此应用中,前端应用程序会持续等待,直到同步API调用完成。因此平均性能虽然看似可以接受,但任何超过一秒钟的响应时长都会给应用程序的交互体验造成严重打击。

为了更深入地了解此项函数的性能,我们为其开启了AWS X-Ray。通过Lambda控制台,我们选定GetQuestions函数,并在AWS X-Ray面板中选中Active tracing复选框。在保存该函数后,X-Ray即正式启用。

我为此项函数重新运行了负载测试,并导航至X-Ray控制台。在Analytics菜单中,Response time distribution面板绘制出了函数调用的性能图:

我选定图中所有位于p95标记之后的调用,其代表着全体请求中响应速度最慢的5%。此过滤器过滤掉34项慢速请求,这些请求与该函数的Metrics控制台中显示的该函数Concurrent Executions(并发执行)次数相对应:

X-Ray列出了速度最慢的34项调用的具体跟踪信息,大家可以选定最慢的单次调用并查看各个细分持续的持续时间:

分析表明,冷启动确实会影响此项函数的性能。在本示例中,执行环境与函数代码的初始化造成了超过1秒的延迟。34项最慢调用中的每一项,都与纵向规模扩展事件有关。

为Lambda函数配置Provisioned Concurrency

Provisioned concurrency 是Lambda中的一项功能,用于在接收流量之前准备执行环境。除了下载函数代码之外,还会执行在Lambda主处理程序之外的初始化代码。通过这种可靠的方式,函数即可做好准备,随时以两位数毫秒级别的延迟做出响应。

从实际来看,所有启用Provisioned Concurrency的函数在启动速度方面都比当前按需Lambda执行方式更快,但不同函数因具体配置不同,获得的速度收益也有所区别。对于C#以及Java这类运行时,其初始化速度要比Node.js或Python慢得多;但在初始化完成之后,后续执行速度则立即反超。在启用Provisioned Concurrency功能之后,这些运行时将显著受益于持续稳定的低延迟启动与更出色的函数执行性能。

要为Lambda函数启用Provisioned Concurrency,请完成以下步骤:

1.前往AWS Lambda控制台,而后选择您的现有Lambda函数。

2.Provisioned concurrency的设置必须明确指向已发布的版本或者别名。前往 Actions 下拉菜单,并选择 Publish new version

3. 选择Publish. 向下滚动至Concurrency面板并选择 Add Configuration

4.输入首选并发,而后选择 Save

5.几分钟之后,Lambda将完成执行环境的准备工作,且控制台内的状态显示为 Ready


这里要再次强调,请务必保证将该功能明确应用于特定函数版本或别名。保证您的调用方法调用的为正确别名,而非$LATEST版本。Provisioned Concurrency不适用于$LATEST版本。

在配置Provisioned Concurrency时,您需要选择要保留的容量。在使用过程中,如果超出容量保留级别,则其余一切函数调用都将继续沿用按需模式。这些调用将延续典型的Lambda启动性能特征,但您以高吞吐量方式运行的调用不会受到与此相关的限制或约束。

使用Amazon CloudWatch Logs,或者通过Lambda控制台上的函数Monitoring选项卡,您可以查看Provisioned Concurrency调用的数量与总数等指标。大家可以借此确定总工作负载何时超过并发量,并据此做出相应调整。

您也可以使用Application Auto Scaling自动配置适当的容量水平。与其保留固定容量,大家不妨在峰值负载期间增加并发量,并随负载降低而逐步减少。您可以在AWS CLI及AWS Serverless Application Model当中进行这方面配置。

Provisioned Concurrency前后的性能比较

现在,我们使用Provisioned Concurrency对同一函数运行相同的负载测试——每秒20次请求,持续2分钟。结果显示,平均延迟为165毫秒,p95时间为202毫秒,最慢执行为532毫秒。

在X-Ray中,最新Response time distribution图显示,2400条请求实现了显著的性能提升:

通过为此Lambda函数启用Provisioned Concurrency,最低性能提升达75%,该函数现在每分钟可以处理1200次请求,同时为用户带来更加一致的性能表现。

函数预热器与Provisioned Concurrency

无服务器社区还通过ping机制开发出开源代码库,用于实现Lambda函数“预热”。这种方法通过Amazon CloudWatch Events每分钟执行一次函数调用,以帮助执行环境始终处于活动状态。如此一来,将大大降低实际调用函数时进行冷启动的几率。

但是,单凭这种方法还不足以彻底消除冷启动问题。当函数出于满足流量需求而进行扩展时,必然在生产环境中引发冷启动状态。此外,如果Lambda服务作为常规负载均衡操作的一部分在另一可用区内运行您的函数,这种方法也同样无法起效。再有,Lambda服务会定期获取执行环境以保持最新状态,因此有可能在不同ping操作之间调用函数。无论属于哪种情况,我们在使用预热库后仍会偶尔遭遇冷启动问题。

换句话说,这种预热方法确实能够为开发/测试环境或者低流量/低优先级工作负载提供良好的冷启动回避效果。但如果您需要以稳定且可预测的启动时间处理工作负载,我们仍然建议您使用Provisioned Concurrency达成目标。它将使您的函数保持在初始化状态,并随时能够以两位数毫秒做出响应。

总结

本文探讨了冷启动如何影响Web应用程序中无服务器后端的性能表现。其中提到,最核心的性能因素往往体现在前端应用程序调用的同步API身上。在这里,我们也进一步了解了Lambda服务中可用于定位冷启动问题的选项。

结合Ask Around Me应用程序,我们在对延迟最为敏感的Lambda函数中应用Provisioned Concurrency功能,并比较了功能启用前后的负载测试性能。结果显示,启用后的函数启动时间可预测性更强,最低执行时间减少了75%。最后,我们又了解了何时适合使用函数预热器,以及哪些延迟敏感型与生产级工作负载更适合使用Provisioned Concurrency。

关于Provisioned Concurrency功能的更多详细信息,请参阅Lambda费率标准页面

本篇作者