Serverless冷启动优化藏在毫秒里的真实取舍
上周在南京线下的技术聚会上,有个做电商售后的工程师蹲在走廊跟我吐槽,说大促当天的优惠券核销接口,有近3成请求头一秒的延迟直接把用户走了。查了三天,不是数据库慢查询,不是带宽堵,是Serverless冷启动优化环节没做好,函数实例冷启动把响应时间拖垮了。
你以为的冷启动,其实根本不是你算的那个数
很多人对冷启动的认知还停留在“函数实例没了,重新拉一个出来”的层面,算优化收益的时候只盯着业务代码的执行时间算。真到落地的时候才发现,完整的冷启动链路长着呢——云厂商的实例调度排队、底层容器镜像拉取、语言运行时初始化、第三方依赖包加载、业务逻辑的初始化执行,每一个环节都可能吃掉几百毫秒的时间。
别笑。真的有团队之前算优化收益的时候,只把函数代码编译时间算进去,最后上线发现总耗时还是降不下来——光运行时的基础镜像拉取就占了60%的冷启动时间,谁能想到。
冷启动的耗时从来不是单一环节的问题。网上传的很多优化方案,要么只盯着某一个环节使劲,要么故意隐去背后的成本,看着收益很高,真照着做了才发现踩坑。
那些传了好几年的优化手段,到底哪个真的能用
先说最常被提到的精简镜像。很多教程说把镜像从1G压到100M,冷启动能快80%。听着确实诱人。麻烦在于,你压镜像的时候,是不是把平时用得到的运行时依赖给砍了?之前有个团队为了压镜像大小,把Node.js里的常用polyfill全删了,结果冷启动是快了200ms,线上跑的时候遇到老版本微信的兼容问题,出了三次线上故障,算下来的故障损失比冷启动那点延迟带来的用户流失还多。
再就是预留并发功能。几乎所有云厂商都推这个功能,就是提前给你留好几个热实例,请求来了直接响应,根本不会触发冷启动。听着是完美方案。但你算过账吗?预留的实例是不管你用不用,都要按小时收钱的。比如你平时一天的请求量集中在早高峰1小时,剩下23小时都是低流量,你预留10个实例,那剩下的23小时你相当于花了23倍的冤枉钱。
说白了,这就像你为了怕早上打不到车,天天在小区门口包一辆出租车等你,哪怕你根本不出门。
还有个被吹得很神的代码懒加载。就是把非核心路径的依赖放到请求进来之后再加载,比如优惠券接口里,那个用户等级的查询SDK,本来是函数初始化的时候就加载的,现在改成第一次调用的时候再加载,这样初始化的时间能降下来。但是代价是什么?第一次触发这个调用的请求,还是会遇到延迟,甚至比原来的冷启动还慢,因为本来初始化的时候就加载完的东西,现在要等请求来了再加载。
这事没那么玄。没有哪一个优化手段是没有代价的,全看你愿意把成本挪到哪个环节去。

算清楚账再动手,比盲目抄方案有用
我见过太多团队,一上来就照着网上的优化清单抄,把所有能开的优化功能全打开,最后第一个月的账单出来吓一跳。之前有个做内容社区的团队,一开始照着教程,把所有函数的预留并发开到了10,镜像压到最小,代码全做了懒加载,结果Serverless账单比之前用虚拟机的时候还高了3成,冷启动延迟确实降了,但是钱花得冤枉。
为什么会这样?因为他们从一开始就没搞清楚,哪些函数真的需要做Serverless冷启动优化。比如后台的定时任务,每天凌晨跑一次的那种,哪怕冷启动要3秒,又有什么关系?根本没人等这个接口的响应。比如面向C端的、用户每次点一下就要等的接口,才值得花成本去优化冷启动。
优化的前提是先搞清楚,你的冷启动延迟到底会不会真的影响业务结果。比如你是做内部员工审批的接口,哪怕冷启动要5秒,员工点一下等5秒也不会走,根本没必要花那个钱去做优化。但是你是做外卖的下单接口,用户点了提交等3秒,一半人都退出去了,这时候花多少钱优化都是值的。
我之前跟一个云厂商的架构师聊,他说现在很多客户找过来,一上来就要求把所有函数的冷启动延迟降到100ms以内,问清楚才知道,他们的函数根本就没有面向C端的请求,全是内部的定时数据处理任务,哪怕冷启动要10秒都不影响。你说这钱花得冤不冤?
上周那个吐槽的电商工程师后来怎么解决的?他没开全量预留并发,也没把镜像压到极致。他把优惠券核销的核心依赖单独抽出来,在函数初始化的时候只加载这部分,非核心的用户积分、推荐信息的SDK全改成了请求进来再加载,然后给高峰期的两个小时开了弹性预留,低峰期全关。最后算下来,冷启动的平均耗时从1.2秒降到了280ms,账单只比之前涨了12%。
哦对了,他之前一开始想的方案是全量开预留,算下来账单要涨200%。
哪有什么万能的优化方案啊。全是一笔一笔算出来的账而已。