赛题背景

2019年,UC Berkeley 发布了一篇论文《Cloud Programming Simplified: A Berkeley View on Serverless Computing》,论文中指出Serverless将取代Serverful计算,成为云计算的计算新范式。其弹性伸缩、按需付费、开发人员专注于业务逻辑而无需关心服务器的运维饱受大家青睐。

另一方面,得益于随着硬件技术的不断进步以及算法的不断优化,大模型人工智能技术在各行各业的应用中变得越来越火爆。

同时在 AI 场景下,请求对资源的消耗特别大。应用实例启动之后只能小并发串行处理请求,所以需要非常精准的调度请求和实例数的匹配关系。

阿里云 ASK(Serverless Kubernetes )阿里云函数计算 FC,都支持资源的按需调度和使用,可以根据应用实际需要资源自动伸缩。在伸缩的过程中涉及到资源的分配,在分配资源的时候会有冷启动问题。另外应用代码的初始化也有冷启动的情况,应用端到端冷启动的时长, 短则是毫秒级,长则分钟级,如果每次实时调用都行进行初始化/销毁应用实例,调用的延时可能无法接受。所以 Serverless 框架会预热应用实例,且在调用结束后保留部分实例,闲置一段时间无调用后再释放,以降低冷启动的概率, 但更多空闲实例的存在,会增加资源成本。

Serverless 场景需要有一个网关承接流量,请求到达网关后被转发到后端实例上。同时需要一个 Scaler 来控制后端实例数,使得实例数和请求对资源的诉求尽量匹配。

Scalar需要遵循 gRPC 协议,实现Assign、Release两个接口

  • Assign: 为请求分配一个应用实例,一个应用实例只能被分配给一个请求,如果无应用实例存在则需要冷启动,重新创建一个实例。
  • Release: 释放请求占用的应用实例,这个实例如果没有被回收, 可以被下次调用请求复用

赛题优化

生产者消费者模型引入

  1. 首先对Demo进行分析

demo

在 Assign 过程:
如果触发了冷启动,将创建新实例来执行当前请求,在创建实例的过程中,新加入空闲队列的实例无法被复用。

初步解决方案:

使用一个协程执行创建实例逻辑

同时主协程轮询空闲实例列表,当存在空闲实例时,立即为请求分配实例,而不等待实例创建完成。
但是该方案仍然存有缺点,访问scalar的空闲实例列表需要获取锁,轮询会导致程序性能下降。

最终解决方案:使用生产者消费者模型

利用信号量机制阻塞请求对应的协程

当空闲队列非空时,唤醒协程,并将实例分配到请求。

优化 GC「资源」

分析

大量实例释放时,空闲队列实例数量激增,而后续请求水平较低。

资源(内存)消耗型的请求稀疏,实例空闲过久影响资源分

设计

当空闲队列实例数超过10时,立即释放实例,而不等待GC_Time

对资源占用较大的实例(2G),维持实例数 <= 1

预配置并发

分析

当在非常短的时间内有快速大量的实例被创建,这个实例会被认为是热点实例,并在接下来的时间内会被使用。这种实例需要提前创建好,减少冷启动发生的数目。

如何创建

对于这种实例,每当因为冷启动而触发create时,为其多创建两个。

如何回收

设置一个时间间隔,过一段时间后,预留两个作为备用。

继续设置一个时间间隔,过了这个时间间隔后,如果没有被访问,将其释放。

优化 GC_Time

方案采取了论文《Serverless in the Wild: Characterizing and Optimizing the Serverless Workload at a Large Cloud Provider》的思想。

分析

统计发现,请求到来间隔存在一定的规律性,如 Roles1 为一个定时请求:每隔 30s 到来若干次。

因此,可以根据请求到来的规律,在请求到来前即创建好实例,从而大幅减少甚至消除冷启动时间。

设计

预热窗口:在得到应用请求间隔统计图基础上,实现实例预热。即请求执行结束后实例被立即释放,经过预热窗口大小后,再次创建实例。

保活窗口:当实例被预热后持续运行时间

验证

部分类型请求在线上与线下的请求到来的规律一致,即具有相同的分布,实验表明在该类型 key 上使用直方图策略具有较好效果。

但仍存在大部分其他类型请求失效的情况,即直方图策略不起作用。

分析以上问题的原因在于即使是同一类型的请求,其在线上与线下的分布并不一致,甚至存在较大偏差,从而使得策略无效。

其实在论文中是讲了在线的整个流程的,但由于参加时间较短,进行完美的复现论文时间紧张,所以我们只针对数据进行了离线的处理,有兴趣的可以去看一下论文原文。

分数据集手动设定 GC_Time

分析

不同数据集请求类型与频率具有明显差异。

数据集一中的请求稀疏,但并发度较高(QPS大)。

数据集二请求密集,但并发度较低,同时实例占用资源较小

设计

针对数据集一,在请求释放后,设定 GC_Time 为较小值,避免大量空闲实例堆积。

针对数据集二,实例占用资源较低,适当延长实例 GC_Time。

心得体会

  1. 非常感谢大赛举办团队,感受到了阿里人对技术的追求
  2. 比赛我们学会了如何更好的沟通与合作,加强了团队的协作能力和凝聚力
  3. 大大提高了我们的技术能力和协作开发能力,在比赛过程中不断探索,不断成长

[NOTE] 还能优化的点:

看了其他组的优化后,还可以优化「执行时间」,对于哪些明显执行时间高于冷启动时间的实例,可以快速 gc 掉。

PS: 拿了个第四,还是很开心的