函数计算性能福利篇(二) —— 业务冷启动优化

本文涉及的产品
函数计算FC,每月15万CU 3个月
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
简介:

继前一篇《函数计算性能福利篇——系统冷启动优化》,我们再来看看近期函数计算推出的 Initializer 功能之后,带来的一波高能性能优化成果。

背景

函数计算是一个事件驱动的全托管 serverless 计算服务,用户可以将业务实现成符合函数计算编程模型的函数,交付给平台快速实现弹性高可用的云原生应用。

用户函数调用链路包括以下几个阶段:

  • 系统为函数分配计算资源;
  • 下载代码;
  • 启动容器并加载函数代码;
  • 用户函数内部进行初始化逻辑;
  • 函数处理请求并将结果返回。

其中前三步是系统层面的冷启动开销,通过对调度以及各个环节的优化,函数计算能做到负载快速增长时稳定的延时,细节详见 函数计算系统冷启动优化
第4步是函数内部初始化逻辑,属于应用业务层面的冷启动开销,例如深度学习场景下加载规格较大的模型、数据库场景下连接池构建、函数依赖库加载等等。为了减小应用层冷启动对延时的影响,函数计算推出了 initializer 接口,便于用户抽离业务初始化逻辑。这样用户就能将自身业务的初始化逻辑和请求处理逻辑分离,分别是实现在 initializer 接口和 handler 接口中,使得系统能识别用户函数的初始化逻辑,从而在调度上做相应的优化。

Initializer 功能简介

引入 initializer 接口的价值主要体现在如下几个方面:

  • 分离初始化逻辑和请求处理逻辑,程序逻辑更清晰,让用户更易写出结构良好,性能更优的代码;
  • 用户函数代码更新时,系统能够保证用户函数的平滑升级,规避应用层初始化冷启动带来的性能损耗。新的函数实例启动后能够自动执行用户的初始化逻辑,在初始化完成后再处理请求;
  • 在应用负载上升,需要增加更多函数实例时,系统能够识别函数应用层初始化的开销,更精准的计算资源伸缩的时机和所需的资源量,让请求延时更加平稳;
  • 即使在用户有持续的请求且不更新函数的情况下,FC系统仍然有可能将已有容器回收或更新,这时没有平台方(FC)的冷启动,但是会有业务方冷启动,Initializer可以最大限度减少这种情况;

具体的 Initializer 功能设计和使用指南,请参考官方 Initiliazer 介绍

初始化场景性能对比

上一节已经简单了概括了 Initializer 的功能,这里,我们具体展示一下初始化场景下 Initializer 带来的巨大的性能提升效应。

函数实现

初始化应用场景,如果不使用 initializer,那么函数的主要实现方式应该是 Global variable 方式,下面提供两种实现方式的 demo ,仅供参考,下面的性能测试也是对比这两种函数实现方式进行了。

使用 global variables 实现业务层初始化逻辑:

# -*- coding: utf-8 -*-
import time
import json

isInit = False
def init_handler():
  time.sleep(30)
  global isInit
  isInit = True

def handler(event, context):
  evt = json.loads(event)
  funcSleepTime = evt['funcSleepTime']
  if not isInit:
       init_handler()
  time.sleep(funcSleepTime)

使用 initializer 的编程模型实现业务层初始化逻辑:

# -*- coding: utf-8 -*-
import time
import json

def init_handler(context):
  time.sleep(30)

def handler(event, context):
  evt = json.loads(event)
  funcSleepTime = evt['funcSleepTime']
  time.sleep(funcSleepTime)

两个 function 的逻辑相同:

  • 函数实例运行时,先执行 init_handler 逻辑,执行时间 30s,进行业务层初始化;
  • 如果已经初始化,那么就执行 handler 逻辑,执行时间 0.1s,进行请求处理;如果没有初始化,那么先进行初始化逻辑,再执行 handler 逻辑。

场景对比

这里根据生产用户请求场景,我们选择如下三种测试 case 来对比两种初始化函数实现的性能。

  • 负载持续增加模式
  • 波峰 burst 模式
  • 业务逻辑升级模式

测试函数的特性如下:

  • 函数 handler 逻辑运行时间为 100ms;
  • 函数 初始化 逻辑运行时间为 30s;
  • 函数代码包大小为 50MB;
  • runtime 为 python2.7;
  • Memory 为 3GB 。

这样的函数,系统层冷启动时间大约在 1s 左右,业务层冷启动在 30s,而函数自身请求执行时间为100-130ms。

负载持续增加模式

该模式下,用户的请求在一段时间内会持续增长。设计请求行为如下:

  • 每波请求并发数翻倍递增: 1, 2, 4, 8, 16, 32;
  • 每波请求的时间间隔为 35s。

TPS情况如下,增长率为100%:

image.png

注意:忽略第一批请求的完全冷启动的延时影响。

不使用 initializer 实现的运行结果:

image.png

image.png

从每波请求的请求延时可以看出,虽然系统层的调度能够为后来的骤增的请求分配更多的函数实例,但是因为函数实例都没有执行过业务层的初始化逻辑,所以新的函数实例花费了大量的执行时间在初始化逻辑的执行上,所以看到 99th latency 都大于 30s 。实际上,系统层的调度优化在这样长时间的初始化场景中并起不了作用。

使用 initializer 实现的运行结果,可以看到使用 initializer 功能之后,请求增长率在 100% 的情况下不会再有函数实例执行初始化逻辑,相对于优化前,99th latency 下降了 30 倍以上。

image.png

image.png

波峰 burst 模式

波峰burst模式是指用户请求比较平稳,但是会有突然的波峰流量场景。设计请求行为如下:

  • 每波请求时间间隔 35s;
  • 每波平稳请求数 2;
  • burst 请求数 18;
  • TPS请求如下,burst 流量猛增 9 倍:

image.png

注意:忽略第一批请求的完全冷启动的延时影响。

不使用 initializer 实现的运行结果:

image.png
image.png

使用 initializer 实现的运行结果,对于 burst 的流量,基本能够将 latency 的增长控制在 函数处理逻辑 6 倍以内,99th 的 latency 被优化到原来的 2.9% 。

image.png
image.png

 业务逻辑升级模式

业务逻辑升级模式是指用户请求比较平稳,但是用户函数会持续 UpdateFunction,变更业务逻辑,进行用户业务升级。设计请求行为如下:

  • 每波请求时间间隔 35s;
  • 每波平稳请求数 2;
  • 每 6 波请求进行一次 UpdateFunction 操作;

TPS 如下:

image.png

注意:忽略第一批请求的完全冷启动的延时影响。

不使用 initializer 实现的运行结果,这个时候请求又会重新执行一次初始化逻辑,导致毛刺出现。

image.png
image.png

使用 initializer 实现的运行结果,基本看出,UpdateFunction 操作对请求已经没有影响,业务层无感知。

image.png
image.png

总结

综上数据分析,函数计算的 Initializer 功能极大的优化了业务层冷启动的毛刺影响:

  • 在用户请求存在明显 burst 或者在以一定速率增长的情况下,能够极大的缓解性能影响,如上,在负载持续增加模式和波峰模式场景下,请求平均 latency 仅仅增加 3 倍,99th latency 只增加了 5 倍,99th latency 仅为优化前的 2.9% ,整整下降了 33 倍之多。
  • 在用户有持续的请求且不更新函数的情况下,优化之后更新函数,业务层能够做到无感知,平滑热升级。

Initializer 功能对业务层冷启动的优化,又一次大大改善了函数计算在延时敏感场景下的表现!

相关实践学习
【文生图】一键部署Stable Diffusion基于函数计算
本实验教你如何在函数计算FC上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。函数计算提供一定的免费额度供用户使用。本实验答疑钉钉群:29290019867
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
相关文章
|
3月前
|
关系型数据库 MySQL Serverless
探索PolarDB MySQL版:Serverless数据库的灵活性与性能
本文介绍了个人开发者对阿里云PolarDB MySQL版,特别是其Serverless特性的详细评测体验。评测涵盖了产品初体验、性能观测、Serverless特性深度评测及成本效益分析等方面。尽管试用过程中遇到一些小问题,但总体而言,PolarDB MySQL版表现出色,提供了高性能、高可用性和灵活的资源管理,是个人开发者和企业用户的优秀选择。
|
23天前
|
关系型数据库 Serverless 分布式数据库
扩缩容操作对PolarDB Serverless的性能有多大影响?
PolarDB Serverless 的扩缩容操作对性能会产生一定的影响,但通过合理的规划、监测和措施,可以将这种影响控制在较小的范围内。同时,随着技术的不断进步和优化,扩缩容操作对性能的影响也会逐渐减小,为用户提供更稳定、高效的数据库服务体验。
|
22天前
|
监控 Serverless 云计算
探索Serverless架构:开发实践与优化策略
本文深入探讨了Serverless架构的核心概念、开发实践及优化策略。Serverless让开发者无需管理服务器即可运行代码,具有成本效益、高可扩展性和提升开发效率等优势。文章还详细介绍了函数设计、安全性、监控及性能和成本优化的最佳实践。
|
23天前
|
监控 关系型数据库 Serverless
扩缩容操作对 PolarDB Serverless 性能的影响
扩缩容操作对 PolarDB Serverless 性能的影响
22 3
|
1月前
|
运维 Serverless 数据处理
Serverless架构通过提供更快的研发交付速度、降低成本、简化运维、优化资源利用、提供自动扩展能力、支持实时数据处理和快速原型开发等优势,为图像处理等计算密集型应用提供了一个高效、灵活且成本效益高的解决方案。
Serverless架构通过提供更快的研发交付速度、降低成本、简化运维、优化资源利用、提供自动扩展能力、支持实时数据处理和快速原型开发等优势,为图像处理等计算密集型应用提供了一个高效、灵活且成本效益高的解决方案。
88 1
|
2月前
|
运维 监控 Serverless
利用Serverless架构优化成本和可伸缩性
【10月更文挑战第13天】Serverless架构让开发者无需管理服务器即可构建和运行应用,实现成本优化与自动扩展。本文介绍其工作原理、核心优势及实施步骤,探讨在Web应用后端、数据处理等领域的应用,并分享实战技巧。
|
2月前
|
运维 Serverless 数据处理
Serverless架构通过提供更快的研发交付速度、降低成本、简化运维、优化资源利用、提供自动扩展能力、支持实时数据处理和快速原型开发等优势,为图像处理等计算密集型应用提供了一个高效、灵活且成本效益高的解决方案。
Serverless架构通过提供更快的研发交付速度、降低成本、简化运维、优化资源利用、提供自动扩展能力、支持实时数据处理和快速原型开发等优势,为图像处理等计算密集型应用提供了一个高效、灵活且成本效益高的解决方案。
63 3
|
4月前
|
存储 缓存 Serverless
函数计算产品使用问题之首次启动时间非常长,该怎么优化
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
4月前
|
缓存 运维 Serverless
函数计算产品使用问题之怎么优化HTTP Server的启动速度
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
4月前
|
监控 Java Serverless
Serverless 应用的监控与调试问题之PyFlink对于Python UDF的性能如何提升
Serverless 应用的监控与调试问题之PyFlink对于Python UDF的性能如何提升

热门文章

最新文章

相关产品

  • 函数计算
  • 下一篇
    DataWorks