并发高性能架构最佳实践

最近更新时间:2024-09-02 16:59:41

我的收藏
并发是云函数在某个时刻同时处理的请求数。在业务其他服务可以支撑的情况下,您可以通过简单的配置实现云函数从几个并发到数以万计并发的拓展。

应用场景

高 QPS 短运行时长

使用云函数进行简单的数据、文件处理,例如对象存储触发云函数进行信息上报、对文件处理等。此类场景下单次请求运行时间较短。

重计算长时间运行

使用云函数进行音视频转码、数据处理、AI 推理等场景,由于模型加载等操作导致函数初始化时间长、函数运行的时间长。包括 Java 运行环境的初始化时间较长。

异步消息处理

使用云函数做异步消息处理的场景较多,例如全景录制场景,腾讯云自研的全景录制,主打所见即所得的录制理念;TDMQ 函数触发场景,可最大程度的衔接消息队列两端的数据上下游,帮助用户实现 Serverless 体系下的异步事件解耦和削峰填谷的能力等。

产品优势

通过综合使用最大独占配额、预置并发等能力,您可以灵活调配多个函数间的资源用量情况,并按需预热函数。

共享配额

在未进行各项配置的情况下,各函数默认共享使用账号额度。如果有某个函数产生了突增业务调用,可以充分利用空闲未使用的额度,来保证突增不会引起函数的调用并发超限。

并发保障

如果有某个函数的业务功能比较敏感或关键,需要尽力保障请求的成功率,此时可以使用最大独占配额。最大独占配额可以给到函数独享额度,确保并发的可靠性,不会由于多函数的争抢导致的调用并发超限。

预置并发

在函数对冷启动敏感、或代码初始化流程耗时较长、加载库较多的情况下,可以通过设置具体函数版本的预置并发,预先启动函数实例来保障运行。

并发扩容原理

并发实例复用与回收与并发扩容原理详情见 并发概述

示例

例如,广州地域的账号默认并发额度可以支撑128MB函数的1000个并发实例。有大量请求到来时,第一分钟可以从0个并发实例启动到500个并发实例。如果还有请求需要处理,第二分钟可以从500个并发实例启动到1000个并发实例。
下图模拟了业务流量峰值时函数并发处理的具体场景。随着业务请求量不断增加,没有可用并发实例处理新的请求时,函数将启动新的并发实例进行扩容。当达到弹性并发的扩容速度限制时,函数扩容速度逐渐变慢,新的请求将会受到限制尝试重试。接着函数会继续扩容,最终达到函数区域对账户的并发限制。最终在满足业务需求后,请求量逐步减少,函数未使用的并发实例会逐步停止。


预置并发支持并发实例按配置预先启动,同时云函数平台不会主动回收这些实例,会尽可能地保障有相应数量的可以处理请求的并发实例。您可通过此功能,为函数的指定版本设定预置并发额度。通过配置预置并发,可预先进行计算资源的准备,降低冷启动、运行环境初始化及业务代码初始化引起的耗时。下图模拟了函数在处理业务流量峰值的预置并发的真实情况。



场景压测

场景1:高 QPS 短运行时长

此类场景下,QPS 较高单次请求运行时间较短,业务在冷启动的一两秒会有并发高峰。接下来我们通过测试观察流量逐步切换或配置预置并发是否能够缓解冷启动并发高峰。

业务情况

业务信息
指标
函数初始化时长
业务没有初始化的操作
业务运行时长
5ms
QPS
峰值约10w左右

压测任务

我们计划分为三个压测任务,分别对应:完全冷启动、逐步切流量、配置预置并发。 每次压测任务都需要从冷启动开始,不能有热实例在;无其他函数影响。

压测目标

高 QPS 的业务在冷启动的一两秒会有并发高峰,通过流量逐步切换或配置预置并发可以缓解冷启动并发高峰。

压测配置

函数配置
a. 内存:128M,未开启异步执行和状态追踪,关闭日志投递
b. 并发配额:4000 × 128M
c. duration:5ms
d. burst:2000
测试工具
使用 go-wrk 工具,直接调用 RegionInvoke 接口。
1.完全冷启动
2.发布新版本逐步切流量
3.配置预置并发
客户端2k并发,调用2k × 5k次,统计并发执行情况以及冷启动并发情况。
性能表现函数并发执行个数如下图所示,在3分钟内完成了整个并发扩缩容的流程。


函数冷启动数据如下图所示,并发可以瞬时启动,在1分钟内达到了我们设置的 burst 为2000冷启动限制。


该场景下平均 QPS 达到 6w左右,并发可以在1分钟内瞬时启动,burst 冷启动限制正常,在3分钟内完成了这个并发扩缩容的全过程。


客户端2k并发,调用2k × 5k次。新版本1分钟内请求从0并发提升1k、再到2k并发,老版本并发由2000降低到1k、再到0并发,统计新老版本并发次数以及冷启动并发情况。性能表现并发折线图旧版本如下图所示:


并发折线图新版本如下图所示:


冷启动并发折线图旧版本如下图所示:


冷启动并发折线图新版本如下图所示:


从上述数据可以看到,通过逐步发版本切流量的方式可以降低并发的突然高峰。
该函数预置2000个并发。预置启动成功后,2000个并发调用重复5k次,统计并发次数以及冷启动并发情况。性能表现并发折线图如下所示:


冷启动并发如下所示:


可以看到整个区间冷启动数为0。函数请求次数如下图所示:


从上述数据可以看到,通过配置预置实例可以使得并发冷启动数为0,推荐客户配置预置并发来保障性能、避免初始化时间过长的问题。

结论

综上,在高 QPS 短运行时间的场景,使用流量逐步切换可以缓解冷启动并发高峰,同时通过预置并发解决客户认为初始化过程(包含函数冷启动)时间过长的问题。

场景2:重计算长时间运行

业务情况

业务信息
指标
函数初始化时长
10s
业务运行时长
2mins
QPS
约20

压测目标

长时间计算任务的平均 QPS 不高,但由于计算时间长,大量实例处于运行状态,导致云函数的并发很高。此压测场景希望看到云函数在处理大量较长时间运行任务的时候,任务的调度和处理速度。

压测配置

函数配置
a. 内存: 128M 开启异步执行和状态追踪,关闭日志投递
b. 并发配额:2000 × 128M
c. duration: 2min
d. burst:2000
测试工具
使用 ab 工具,模拟 cos 服务的消息,通过函数的 cos 触发器调用函数。

压测任务

每次压测任务都需要从冷启动开始,不能有热实例在;无其他函数影响。

结果分析

4000消息更能印证2000消息时的结论,前两分钟因为之前的函数没有释放,所以冷启动数和函数请求数是一致的,后续冷启动数和函数请求数增长基本保持一致。

结论

长初始化、长运行时间的业务能够稳定运行,系统能够随着请求数瞬时的完成扩缩容。

场景3:异步消息处理

业务背景

使用云函数做异步消息处理的场景较多,这里取运行100ms作为平均值。
业务信息
指标
函数初始化时长
0
业务运行时长
100ms

压测目标

异步消息的消费情况与生产相关,我们假设已经有大量的消息堆积,查看云函数的消费情况。其中会包括消费过程中受到并发限制而后重试的情况,您可以通过灵活调整函数的保留并发,从而控制云函数的消费速度,也就是对下游后台的压力。

压测配置

函数配置
a. 内存: 128M 开启异步执行和状态追踪,关闭日志投递
b. 并发配额:X × 128M
c. duration:100ms
d. burst:2000
测试工具
使用 ab 工具,模拟 cos 服务的消息,通过函数的 cos 触发器调用函数。

压测任务

每次压测任务都需要从冷启动开始,不能有热实例在。
异步消息1k并发
异步消息2k并发
异步消息4k并发
函数保留 2k 并发,投递100w条消息进行消费,记录总消费时间、消息处理的分布情况,并发监控。性能表现并发折线图如下所示:


冷启动折线图如下所示:



函数请求次数如下所示:



共计3分钟,处理完所有消息。
函数保留 2k 并发,投递100w条消息进行消费,记录总消费时间、消息处理的分布情况,并发监控。性能表现并发折线图如下所示:



冷启动折线图如下所示:



函数请求次数如下所示:



共计2分钟,处理完所有消息。
函数保留 4k 并发,投递100w条消息进行消费,记录总消费时间、消息处理的分布情况,并发监控。性能表现并发折线图如下所示:



冷启动折线图如下所示:



Dashboard 上函数冷启动数据,该冷启动有 burst 超限。
函数请求次数如下所示:



共计1分钟,处理完所有消息。

结果分析

1. 1000并发配额提升到2000并发配额时,能看到函数的处理速度,包括函数并发等明显提升,所以在大量异步消息时提高并发配额可以提升消息处理速度。
2. 2000并发配额提升到4000时,消息处理速度和函数并发量也有提升,但总体处理时间也在2分钟内,说明100w条异步消息时,4000肯定也能提升,但2000配额基本已满足场景需求。
3. 4000并发配额时会有 burst 超限的问题,因为并发配额是4000,burst 是2000,所以大量消息时肯定会有超限的情况发生。

结论

大量异步消息场景,提升函数并发配额,能明显提升消息处理速度,符合预期。 您可以灵活控制函数并发,进而控制异步消息的消费速度。

注意事项

预置并发功能只对已经配置并启动、但未使用的实例收取少量闲置费用,对于已配置且在使用的实例不收取额外费用。即只有当前版本的预置数量大于版本并发数时,会收取超出部分的闲置费用。未超出的部分不额外收费。详情见 计费概述