并发是云函数在某个时刻同时处理的请求数,在业务其他服务可以支撑的情况下,您可以通过简单的配置实现云函数从几个并发到数以万计并发的拓展。
01.
应用场景
1. 高 QPS 短运行时长
使用云函数进行简单的数据、文件处理,例如对象存储触发云函数进行信息上报、对文件处理等。此类场景下单次请求运行时间较短。
2. 重计算长时间运行
使用云函数进行音视频转码、数据处理、AI 推理等场景,由于模型加载等操作导致函数初始化时间长、函数运行的时间长。包括 Java 运行环境的初始化时间较长。
3. 异步消息处理
使用云函数做异步消息处理的场景较多,例如全景录制场景,腾讯云自研的全景录制,主打所见即所得的录制理念;TDMQ 函数触发场景,可最大程度的衔接消息队列两端的数据上下游,帮助用户实现 Serverless 体系下的异步事件解耦和削峰填谷的能力等。
02.
产品优势
通过综合使用最大独占配额、预置并发等能力,您可以灵活调配多个函数间的资源用量情况,并按需预热函数。
1. 共享配额
在未进行各项配置的情况下,各函数默认共享使用账号额度。如果有某个函数产生了突增业务调用,可以充分利用空闲未使用的额度,来保证突增不会引起函数的调用并发超限。
2. 并发保障
如果有某个函数的业务功能比较敏感或关键,需要尽力保障请求的成功率,此时可以使用最大独占配额。最大独占配额可以给到函数独享额度,确保并发的可靠性,不会由于多函数的争抢导致的调用并发超限。
3. 预置并发
在函数对冷启动敏感、或代码初始化流程耗时较长、加载库较多的情况下,可以通过设置具体函数版本的预置并发,预先启动函数实例来保障运行。
03.
并发扩容原理
如果请求到来时,没有该版本的并发实例可以处理该请求,云函数平台会启动新的并发实例来处理。新启动的并发实例在初始化的过程后,便可以处理事件,我们称之为由弹性并发带来的扩容。
在地域维度,个人用户账号的 弹性并发的扩容速度默认限制为 500 个/分钟,即在 1 分钟内,最多可以启动 500 个新的并发实例。如在1分钟内已经达到了当前限制,则将无法再启动新的并发实例,持续到下 1 分钟。在此期间有新的并发扩容请求,将会产生扩容受限错误(429 ResourceLimit),详情可参见云函数状态码。
- 云函数状态码:https://cloud.tencent.com/document/product/583/42611
例如,广州地域的账号默认并发额度可以支撑 128MB 函数的 1000 个并发实例。有大量请求到来时,第一分钟可以从 0 个并发实例启动到 500 个并发实例。如果还有请求需要处理,第二分钟可以从 500 个并发实例启动到 1000 个并发实例。
下图模拟了业务流量峰值时函数并发处理的具体场景。随着业务请求量不断增加,没有可用并发实例处理新的请求时,函数将启动新的并发实例进行扩容。当达到 弹性并发的扩容速度 限制时,函数扩容速度逐渐变慢,新的请求将会受到限制尝试重试。接着函数会继续扩容,最终达到函数区域对账户的并发限制。最终在满足业务需求后,请求量逐步减少,函数未使用的并发实例会逐步停止。
预置并发支持并发实例按配置预先启动,同时云函数平台不会主动回收这些实例,会尽可能地保障有相应数量的可以处理请求的并发实例。您可通过此功能,为函数的指定版本设定预置并发额度。通过配置预置并发,可预先进行计算资源的准备,降低冷启动、运行环境初始化及业务代码初始化引起的耗时。下图模拟了函数在处理业务流量峰值的预置并发的真实情况。
04.
并发服务承诺
在地域维度,个人用户弹性并发的扩容速度默认限制为 500 并发/分钟,企业用户为 1000 并发/分钟。例如客户有 10w 并发的诉求,按照最大弹性并发的扩容速度,需要 10w/1000 =100 分钟就能完成扩容操作,需要提升配额可以提交工单联系我们。
每个账号在地域维度有并发的限制,用户无法修改地域级的配额,云函数平台按照个人、企业用户在不同地域配置不同的并发配额,详情见表格,需要提升各项配额可以提交工单联系我们。
- 工单提交地址:https://console.cloud.tencent.com/workorder/category
实例复用与回收
当并发实例处理完事件请求后,不会立刻被回收,而是会保留一段时间以便复用。在保留期内,如有新的请求事件需要处理,将会优先使用保留中的并发实例,从而实现事件的快速处理,无需新启动并发实例。
保留期过后,如果没有请求需要该实例处理,云函数平台则会回收该实例。对于低并发的场景,不再设置保留期,平台将启动智能回收机制进行回收。
并发保留的时间由云函数平台根据情况动态调整,故函数业务代码中不能假设某个特定保留时间进行程序编写。
05.
场景压测
场景 1:高 QPS 短运行时长
此类场景下,QPS 较高单次请求运行时间较短,业务在冷启动的一两秒会有并发高峰。接下来我们通过测试看看流量逐步切换或配置预置并发是否能够缓解冷启动并发高峰。
- 压测任务
我们计划分为三个压测任务,分别对应:完全冷启动、逐步切流量、配置预置并发。每次压测任务都需要从冷启动开始,不能有热实例在,无其他函数影响。
- 压测目标
高 QPS 的业务在冷启动的一两秒会有并发高峰,通过流量逐步切换或配置预置并发可以缓解冷启动并发高峰。
- 压测配置
1. 函数配置
- 内存:128M 未开启异步执行和状态追踪,关闭日志投递;
- 并发配额:4000*128M;
- duration:5ms;
- burst:2000;
2. 测试工具
- 使用 go-wrk 工具,直接调用 RegionInvoke 接口。
1.1 完全冷启动
客户端 2k 并发,调用 2k*5k 次,统计并发执行情况以及冷启动并发情况。
性能表现
(并发执行个数折线图)
函数并发执行个数如上图所示,在3分钟内完成了整个并发扩缩容的流程。
(冷启动并发次数折线图)
函数冷启动数据如上图所示,并发可以瞬时启动,在 1 分钟内达到了我们设置的 burst 为 2000 冷启动限制。
从上述数据可以看到,该场景下平均 QPS 达到 6w左右,并发可以在1分钟内瞬时启动,burst冷启动限制正常,在3分钟内完成了这个并发扩缩容的全过程。
1.2 发布新版本逐步切流量
客户端 2k 并发,调用 2k*5k 次。
- 新版本:1 分钟内请求从0并发提升1k、再到 2k 并发
- 老版本:并发由 2000 降低到 1k、再到 0 并发,统计新老版本并发次数以及冷启动并发情况。
性能表现
(并发执行个数折线图 - 旧版本)
(并发执行个数折线图 - 新版本)
(冷启动并发折现图 - 旧版本)
(冷启动并发折现图 - 新版本)
从上述数据可以看到,通过逐步发版本切流量的方式可以降低并发的突然高峰。
1.3 配置预置并发
该函数预置 2000 个并发,预置启动成功后, 2k 并发调用重复 5k 次,统计并发次数以及冷启动并发情况。
性能表现
(并发执行个数折线图)
(冷启动并发折现图)
可以看到整个区间冷启动数为 0。
(函数请求次数)
从上述数据可以看到,通过配置预置实例可以使得并发冷启动数为 0,推荐客户配置预置并发来保障性能、避免初始化时间过长的问题。
结论
综上,在高 QPS 短运行时间的场景,使用流量逐步切换可以缓解冷启动并发高峰,同时通过预置并发解决客户认为初始化过程(包含函数冷启动)时间过长的问题。
场景 2:重计算长时间运行
业务情况
压测目标
长时间计算任务的平均 QPS 不高,但由于计算时间长,大量实例处于运行状态,导致云函数的并发很高。此压测场景希望看到云函数在处理大量较长时间运行任务的时候,任务的调度和处理速度。
压测配置
1. 函数配置
- 内存: 128M 开启异步执行和状态追踪,关闭日志投递
- 并发配额:2000*128M
- duration:2min
- burst:2000
2. 测试工具
- 使用 ab 工具,模拟 cos 服务的消息,通过函数的 cos 触发器调用函数。
压测任务
每次压测任务都需要从冷启动开始,不能有热实例在;无其他函数影响。
2.1 长初始化、长运行时间场景、每个并发 1 个消息
2000 并发,每个并发 1 个消息,累计投递 2000 个请求。统计从第一个请求到达的开始时间、最后一个请求返回的结束时间,以及请求总处理时间的分布情况。
(并发执行个数折线图)
(冷启动折线图)
(函数请求次数)
结果分析
冷启动个数为何并不是同一分钟内冷启动完成?
1. 异步场景,请求次数并不是一起到达 RegionInvoke,而是通过异步触发器的 worker 调用 RegionInvoke。
2. 因为函数 duration 为 2 分钟,初始化 10 秒钟,总体耗时在 3 分钟内,所以随着函数请求次数的不断提高,但是前面启动的容器还没有释放,需要不停的启动容器来完成请求,函数请求次数每分钟增长的速率基本和冷启动的个数吻合。
3. 函数并发到达最高点时冷启动开始下降,基本吻合符合正常。
2.2 长初始化、长运行时间场景 、每个并发 2 个消息
2000 并发,每个并发 2 个消息,累计投递 4000个 请求。统计从第一个请求到达的开始时间、最后一个请求返回的结束时间,以及请求总处理时间的分布情况。
(冷启动折线图)
(函数请求次数)
结果分析
4000 消息更能印证 2000 消息时的结论,前两分钟因为之前的函数没有释放,所以冷启动数和函数请求数是一致的,后续冷启动数和函数请求数增长基本保持一致。
结论
长初始化、长运行时间的业务能够稳定运行,系统能够随着请求数瞬时的完成扩缩容。
场景 3:异步消息处理
业务背景
使用云函数做异步消息处理的场景较多,这里取运行 100ms 作为平均值。
压测目标
异步消息的消费情况与生产相关,我们假设已经有大量的消息堆积,查看云函数的消费情况。其中会包括消费过程中受到并发限制而后重试的情况,您可以通过灵活调整函数的保留并发,从而控制云函数的消费速度,也就是对下游后台的压力。
压测配置
1. 函数配置
- 内存: 128M 未开启异步执行和状态追踪,关闭日志投递
- 并发配额:X*128M
- duration: 100ms
- burst:2000
2. 测试工具
使用 ab工具,模拟cos服务的消息,通过函数的cos触发器调用函数。
压测任务
每次压测任务都需要从冷启动开始,不能有热实例在。
3.1 异步消息 1k 并发
函数保留 1k 并发,投递 100w 条消息进行消费,记录总消费时间、消息处理的分布情况,并发监控。
(并发折线图)
(冷启动折线图)
(函数请求次数)
共计 3 分钟,处理完所有消息。
3.2 异步消息 2k 并发
函数保留 2k 并发,投递100w条消息进行消费,记录总消费时间、消息处理的分布情况,并发监控。
(并发折线图)
(冷启动折线图)
(函数请求次数)
共计 2 分钟,处理完所有消息。
3.3 异步消息 4k 并发
函数保留 4k 并发,投递 100w 条消息进行消费,记录总消费时间、消息处理的分布情况,并发监控。
(并发折线图)
(冷启动折线图)
Dashboard 上函数冷启动数据,这个冷启动有 burst 超限了。
函数请求次数:共计 1 分钟,处理完所有消息。
(函数请求次数)
结果分析
1. 3.1 场景的 1000 并发配额提升到 3.2 的 2000 并发配额的时候,确实能明显看到函数的处理速度,包括函数并发等都有明显提升,所以在大量异步消息时提高并发配额可以提升消息处理速度。
2. 3.2 的 2000 并发配额提升到 4000 的时,消息处理速度和函数并发量也有提升,但总体处理时间也在 2 分钟内,说明 100w 条异步消息时,4000 肯定也能提升,但 2000 配额基本已满足场景需求。
3. 4000 并发配额时会有 burst 超限的问题,因为并发配额是 4000,burst 是 2000,所以大量消息时肯定会有超限的情况发生。
结论
1. 大量异步消息场景,提升函数并发配额,能明显提升消息处理速度,符合预期。
2. 您可以灵活控制函数并发,进而控制异步消息的消费速度。
说明
- 预置并发功能目前处于内测阶段,识别下方二维码,申请开通此功能,我们将在 7 个工作日内给您答复。
- 内测期间,预置并发能力不计费。预计 11 月正式发布,届时处于空闲的预置并发实例会收取少量费用,处理请求的实例会按照请求的实际执行时间进行费用计算,详见计费概述。
- 计费概述访问地址:https://cloud.tencent.com/document/product/583/17299
推荐阅读
One More Thing
欢迎进入千人 QQ 群 (871445853) 交流 Serverless!
- GitHub: github.com/serverless
- 官网: cloud.tencent.com/product/serverless-catalog
点击「阅读原文」,立即申请使用预置并发功能。