函数计算与冷启动的那些事
本文首先简单介绍冷启动对使用FaaS (Function as a service)的开发者的影响,并介绍函数计算冷启动流程和最佳实践。最后会分享函数计算冷启动延时优化现阶段成果,希望对于被冷启动延时所困扰的开发者有所帮助。
冷启动影响
函数计算的开发者们相信对冷启动的概念并不陌生,其对业务的影响可以总结为:
- 延迟毛刺: 容器启动,下载代码,runtime初始化,业务逻辑初始化这些时间加起来可能将请求耗时拉高至500ms-30s,对于延迟敏感(< 100ms)的应用这样的延迟不可接受。
- 额外工作量: 开发者为了减少冷启动的出现,通常要实现与业务逻辑无关的定时预热功能,例如函数handler需要支持预热,预热函数需要控制并发度。
- 额外费用: FaaS平台通常根据请求时长收费,定时的预热会产生不必要的费用。对初始化时间很长的应用(如深度学习模型初次加载),频繁的冷启动产生额外的费用。
冷启动频率增大是Serverless vs. Serverful 架构引入的一个新的挑战,过高的延迟可能会让对长尾延迟(P99)敏感的业务望而却步。在函数计算中,有什么办法可以减小冷启动的影响呢?
冷启最佳实践
上图介绍了函数计算冷启动的流程。冷启动的优化是一个共享的责任(shared responsibility),它要求开发者:
- 精简紧凑的代码包: 开发者要尽可能瘦身代码包,去掉不必要的依赖。降低Download/Extract Code的时间。例如对Nodejs函数使用npm prune, 对Python函数使用autoflake , autoremove 去除没有使用的依赖。另外一些第三方库中可能会包含test源代码,无用binary,和数据文件。有选择地删除无用文件可以降低函数代码下载解压时间。
- 选择合适的函数语言: 下文图中会看到Python2.7的冷启动时间远低于Nodejs8;函数计算Java8运行时通常冷启动时间要高于其他语言。对于冷启动延迟敏感的应用。在热启动延迟差别不大的情况下,使用Python这样的轻量语言可以大幅降低长尾延迟。
- 选择合适的内存: 下文图中会看到在并发量一定的情况下,函数内存越大,冷启动表现越优。
- 避免不必要的配置: 例如函数A需要访问用户自己VPC而函数B不需要,这时可以新建一个Service,不配置VPC并在新建Service中创建函数B。VPC的初始化需要引入创建并挂载用户ENI,这个操作可能是数秒级别的。因此对于没有需求的函数,不配置VPC功能对冷启动有很大帮助。
-
降低冷启动概率:
- 使用定时触发器 预热函数
- 使用Initializer 函数入口,函数计算会异步调用初始化接口,消除掉“User Code Init” 的时间,在函数计算系统升级或者函数更新过程中,用户对冷启动几乎无感知。
函数计算冷启动延时优化史
在Shared Responsibility另一端,函数计算平台层面做了多层优化:
- 精简系统耗时
- 加速代码下载解压
- 降低容器和进程启动时间
- 降低冷启动概率
相比较6个月前冷启动表现,函数计算延时最多减少80%。在Python2.7大内存的配置下,小代码包 (小于1KB)平均冷启动延迟降低至200ms左右,P95延迟稳定,达到FaaS平台顶级水平。
- 注:benchmark方法为各个函数20并发执行sleep(20s) 函数,调用结束后,间隔30-60分上进行下一次20并发调用。上图是重复在上海region重复跑1星期统计到的数据。
总结
冷启动是Serverless运行环境中开发者必须面对的痛点。开发者可以通过精简代码,选择合适配置降低冷启动的影响。函数计算也将会针对冷启动延时做持续不断的优化,力争让业务函数对冷启动无感知,让Serverless更加完美。
函数计算使用过程中如遇到任何问题欢迎加入 函数计算官网客户群
提问反馈交流。