首页 / 业界 / 正文

Serverless冷启动优化 那些藏在毫秒级延迟里的取舍

上周跟一个做电商的朋友喝咖啡,他说大促刚过复盘,翻监控日志发现,零点刚过的头三分钟,有近两成的接口超时。

不是流量打满。

是Serverless函数冷启动卡了壳。

我当时第一反应,他是不是把所有核心接口都开了纯按需模式?他说对,当初选Serverless就是图不用管服务器,按量付费,没想到栽在这上面。

太常见了。

冷启动的耗时从来不是你想的那样

很多人对冷启动的认知停留在“代码要跑起来总得加载吧”,其实你写的业务代码加载耗时,连总冷启动耗时的10%都占不到。真正的耗时大头,是云平台拉起实例、拉取容器镜像、初始化运行时环境这三个步骤。你写一个接口的逻辑再复杂,哪怕有上千行代码,在Node.js或者Python的运行时里跑起来,也就几十毫秒的事。

Serverless冷启动全链路耗时拆解示意图

我见过太多团队,花了整整两周时间,把Node.js项目的node_modules从400多M砍到30M,连个第三方日志库都换成了自己写的console.log,上线后一测,冷启动耗时只降了210毫秒。转头就去云厂商的工单里骂“你们的毫秒级启动是骗人的”。

麻烦在于,你优化的本来就是占比最小的那部分,当然看不到效果。

真的。

最有效的优化往往是看起来不那么“Serverless”的手段

说实话,我见过这么多Serverless冷启动优化的方案,最后落地效果最好的,反而都是那些打破了“纯按需付费”执念的手段。

比如预留实例池。很多人觉得用预留实例,那我当初选Serverless干嘛?跟买固定的虚拟机有啥区别?但你算过账没有?核心交易接口每天的访问量,至少有80%是集中在白天的固定时段,哪怕你留3个常驻的实例,成本也比你因为接口超时掉的订单钱少得多。

预留实例与按需实例冷启动耗时对比折线图
预留实例与按需实例冷启动耗时对比折线图

还有云厂商现在普遍推的快照恢复功能。就是把已经初始化好的运行时、已经拉完镜像的实例打成快照,等需要新实例的时候,直接从快照恢复,跳过前面最耗时的拉镜像、初始化步骤。我之前测过,同样的Python函数,用快照恢复的启动耗时,能比常规启动降70%,比你花一周砍依赖有用多了。

当然,预留实例不是让你把所有函数都搞成常驻。你要是把那个每天只触发一次的定时清理日志的函数也开了预留,那纯属浪费钱。

别为了降冷启动把弹性的优势全丢了

这事没那么玄。Serverless冷启动优化的核心,从来不是把所有函数的启动耗时都压到100毫秒以内,而是把不同场景的冷启动代价,控制在用户能接受的范围内。

比如你给用户返回结果的核心交易接口,冷启动耗时最好控制在500毫秒以内,不然用户会觉得卡,甚至直接退出页面。但你给后台运维用的、或者异步处理的接口,哪怕冷启动要3秒,也完全没关系——反正用户点了提交之后,你可以先给个“提交成功”的提示,后台慢慢跑就行。

我之前碰到过一个团队,为了降冷启动,把所有函数都开了预留实例,每个月的费用翻了三倍,最后算下来,比原来用虚拟机的成本还高。说白了,他们是把“Serverless的弹性是优势”这句话,给完全忘了。

还有个很多人不知道的小细节:你把运行时需要初始化的全局变量、数据库连接,都放在函数的最外层,不要放在handler里面。这样哪怕函数被复用,这些连接也不用重新初始化,能省不少重复的耗时。

别信那些所谓的“通用冷启动优化框架”,很多框架为了通用性,给你加了一堆你根本用不上的依赖,反而会把你的函数包变大,拖慢启动速度。这事得结合你自己的业务场景算,没有万能的方案。

上周那个做电商的朋友,后来回去把核心交易接口开了5个预留实例,非核心的营销活动接口还是用按需,冷启动率从18%降到了2%,大促的超时率直接没了。

他说早知道这么简单,当初就不用花两周砍依赖了。