Open linxuyalun opened 3 years ago
关于全文的笔记可以见 https://github.com/linxuyalun/paper-reading/blob/master/serverless/faascache/faascache.md
下面把其中一些比较有意思的部分单独拎出来
这篇 paper 将 serverless 中的 keep-alive 问题等价成 caching。亮点在于受 cache 启发提出了一种 Greedy-Dual keep-alive 策略减少冷启动的开销
Keep-alive 的关键思想在于一个 warm function 在短期能很可能被再次调用。理想情况 keep-alive 的长短应当和函数本身的特征强绑定,但是这实际上还是有一定难度的,因为每个 function 的初始化开销,资源 footprint(比如内存和 CPU 的开销)以及请求频率是完全不同的,因此目前所有厂商的做法是提供一个固定的存活时间。
为了继续开展下去 Keep-alive
,我们需要分析一下一个函数从启动到运行所有的开销,如下图:
从图中可以看出,大约花费了 2.5 秒来 loading 所有 runtime 依赖(红色部分);黄色部分代表解决用户代码依赖所花费的时间。这说明,如果保持请求执行完后 alive,红色部分和黄色部分的开销都可以消除。
Keep alive 策略的主要目标是通过让不同特征的函数保持不同的 alive time 来减少初始化和冷启动的开销。
由于使用 FaaS 平台的应用高度多样化,Keep-alive 的策略设计并非易事。使用 FaaS 的应用既包括了一些 Web 服务,也包括一些科学计算,ML 等高内存占用重初始化开销的应用。此外,FaaS 的 Function 具有高动态性和周期性,峰值往往超过平均值的两倍,一些函数的调用频率远远高过其他函数。论文使用以下几个指标去制定策略:
资源是有限的,根据上述特点,可以判定一个函数应该 keep alive 多久。一个偶尔才被调用,不太可能在不久将来再次被调用的函数,keep alive 不仅没什么好处,而且还占内存;保持那些 large-footprint 的代价要比一些小函数高昂的多,那么那些小函数可以存活更长的时间;函数可以根据初始化开销进行优先排序,因为初始化开销实际上消耗了计算。
目前的 FaaS 使用原始的 keep-alive 策略,这些策略的设计没有考虑到函数本身的多样性和动态性。比如 OpenWhisk,将所有函数保持在一个恒定的时间段(10分钟)。
这篇论文的一大亮点在于它证明了 ”keeping functions alive is equivalent to keeping objects in a cache“:
GDSF 算法(Greedy-Dual-Size- Frequency,贪婪双尺寸频率缓存替换算法)算法是一种基于 Web 缓存的缓存算法。
该算法的基本思想是是使用某个目标保存价值函数来计算出缓存中所有缓存对象的保存价值 H,当缓存剩余空间不足以保存新的对象时,根据这个 H 值将缓存对象由高到低进行排序,优先将缓存中保存价值 H 最低的对象替换出去。目标函数为:
回到本文的 keep-alive 策略,它就是基于 GDFS 设计的一个算法,它的核心思想是只要服务器资源够,进程中的函数资源尽可能的保持 warm,这其实和之前那些 FaaS 的做法是截然不同的,恒定时间的生存策略意味着即使有资源可以让它们生存更长时间,也会被终止。Greedy-Dual Keep-Alive Policy 更多是作为一种驱逐策略,如果要启动一个新的容器,并且没有足够的资源可用,那么我们要终止哪个容器。显然,容器的总数(warm + running)受服务器物理资源(CPU 和内存)限制,这篇论文就根据函数冷启动的开销和资源占用情况为每一个容器计算一个优先级,并终止优先级最低的容器。
优先级计算:对于每一个容器,它都有一个自己的 keep-alive 优先级,主要基于函数调用频率,运行时间,函数大小:
当一个 Warm 函数被重用了,就相当于发生了一次 “cache hit”,接下来将重点解释这几个参数的含义:
Clock:Clock 用来记录函数的实效性,每个 server 会维护一个逻辑时钟,在每次发生驱逐时更新。每次一个容器被使用的时候,它的 Clock 就会被更新,因此,最近没有使用的容器会有较小的 Clock。当没有足够资源启动新的容器,现有的 warm 容器无法被使用时,一个容器就会被终止。具体来说,如果一个容器 J 被终止了,那么 J 一定是最小优先级,那么 Clock = PriorityJ,此后被使用的容器在更新自身 Clcok 值时就会使用改值;
Frequency:Frequency 是指一个给定函数被调用的次数。一个函数可以被多个容器执行,Frequency 表示其所有容器中函数调用的总次数。当一个函数的所有容器被终止时,Frequency 被设置为零。优先级与频率成正比,因此,更频繁执行的函数会保持更长的时间;
Cost:Cost 代表终止成本,它等于总的初始化时间,这体现了保持容器 alive 的好处以及冷启动的成本。因此,优先级和初始化开销成正比;
Size:Size 是容器的 resource footprint,在大多数情况下,可以运行的容器数量受物理内存可用性的限制,因为 CPU 很容易被复用但是内存交换会导致严重的性能下降,因此这里的 Size 考虑的是容器内存的使用。
ASPLOS ’21
https://dl.acm.org/doi/10.1145/3445814.3446757