
# Serverless性能优化
**Serverless函数配置最佳实践**
- 运行时语言
当选择编译型语言（如Java，C#等），冷启动时延一般由于首次初始化消耗比较大会导致冷启动时延偏高，但是初始化完成后每次执行的时延相较其他解释型语言（NodeJs，Python等）会有一定优势。如果流量不均衡，且对冷启动时延或者最大时延有一定要求的业务使用NodeJs, Python等运行时语言，如果流量比较均衡或者对最大时延不敏感，但是对平均时延敏感的业务选择Java，Go等编译型语言。
- 内存规格
函数Pod中分配的CPU资源与内存规格成正比，所以更大的内存规格可以获得更高的CPU资源从而提升执行性能。如果业务场景为CPU密集型或者需要大量使用内存的，建议配置更大的内存规格来获取更低的执行时延，可以通过配置不同大小内存进行性能测试，观察时延监控结合业务实际预算选择合适的内存规格。
同时如果同一个函数在不同场景下对内存和CPU资源的要求不一样，可以使用动态内存能力。参考[配置动态内存](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_0310.html)。
- 最大实例数
如果函数执行并发量较大，那么默认的最大实例数可能不足以支撑业务调用，如果超出最大实例数对应的处理能力，可能造成执行排队时延升高，甚至出现报错。建议最大实例数和业务实际最大并发数保持一致。
- 预留实例数
预留实例是将函数实例的创建和释放交由用户管理，当您为某一函数创建了预留实例，函数工作流收到此函数的调用请求时，会优先将请求转发给您的预留实例，当请求的峰值超过预留实例处理能力时，剩余部分的请求将会转发给按量实例，由函数工作流自动为您分配执行环境。如果业务流量不均衡，存在波峰波谷情况，且对冷启动时延有要求的可以结合实际预算配置一定数量预留实例，同时，如果业务波峰波谷存在周期规律的，也可以配置预留实例的定时伸缩和智能预测弹性策略，提升资源利用率，减少资源浪费。参考[预留实例管理](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_1837.html)。
网络配置
公网访问：函数提供了公网访问能力，但是函数提供的公网出口带宽有限，且所有租户共享，只适合对带宽、可靠性要求较低的测试业务使用。
VPC访问：函数提供了指定VPC访问的能力，但在冷启动时会初始化到该VPC网络的网络链路造成额外的冷启动时延。
如果需要访问公网，且对带宽有要求的生产业务可以通过配置绑定了NAT网关的VPC来访问公网；如果函数没有网络访问场景的，不建议配置VPC。参考[配置网络](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_0222.html)。
- 超时时间
如果函数配置的超时时间比较长的话，且函数代码中发生异常导致阻塞，函数同步调用会等待直到超出超时时间才返回超时异常，造成业务卡顿，长时间不退出等问题，无法实现failfast，影响业务体验。建议结合业务实际场景配置超时时间，避免超时时间配置过大。
**Serverless函数代码最佳实践**
如果业务可以异步实现，那么不需要关心函数的性能（除了优化成本之外）。FunctionGraph函数的性能很大程度上取决于需要FunctionGraph函数执行何种逻辑。
策略：
- 正确的使用连接池，保持连接存活并重用在上一次调用中建立的连接（HTTP，数据库、redis等）。

- 通过接口调用FunctionGraph函数时，建议客户端维护http连接池，减少http连接初始化时间。
- 避免在每次调用时重新初始化变量对象（使用全局静态变量、单例等）。
- 选择解释性语言（nodejs、python）而不是编译型语言（java、go）。
- 精简函数代码包，满足其运行时需要即可。 这将大幅减少在调用前从华为云 OBS下载代码包所花费的时间。
- FunctionGraph函数调用华为云其他云服务资源时（例：dis、obs），如果选择对应云服务sdk，需要对sdk参数进行调优（例：超时时间、连接数、重试次数等）。
- FunctionGraph函数中访问第三方服务或华为云服务时，性能上限受第三方服务或华为云服务的性能上限制，需要确保访问的服务无性能瓶颈。
**冷启动优化实践**
Serverless按用付费、自动弹性伸缩、屏蔽复杂性等特征使其逐渐成为下一代云计算新范式。但是在Serverless架构带来极大便利的同时，在实时性要求较高的应用场景下，冷启动将是面临的一个挑战。当使用serverless构建 Web 服务时，冷启动和Web服务初始化时间一共超过了5秒钟，那么无疑将会使用户体验大打折扣，因此设法减少冷启动时间，提高终端用户的使用体验，是构建无服务器架构时亟待解决的问题。
Serverless实例的生命周期可以分为三个阶段：初始化阶段、执行阶段、关闭阶段。
当触发FunctionGraph时，若当前没有处于激活阶段的函数实例可供调用，则会下载函数的代码并创建一个函数的执行环境。从事件触发到新的FunctionGraph环境创建完成这个周期通常称为 冷启动时间。在serverless架构中，冷启动问题是无法避免的。
目前FunctionGraph已经对系统侧的冷启动做了大量优化，针对用户侧参考以下方案。：
- 选择合适的编程语言
目前FunctionGraph支持的编程语言（Runtime）有 .NET Core、Go、Java、Node.js、Python。在默认 512MB 内存的情况下，我们创建不同语言的函数，做一个冷启动时间横向的测试和比较。各个语言的冷启动时间为JAVA\>GO\>.NET\>Node.js\>Python。
- 选择合适的内存
在请求并发量一定的情况下，函数内存越大，分配的CPU资源相应越多，一般冷启动表现越优。
- 快照冷启动
Java应用冷启动速度慢的问题尤为突出。华为云FunctionGraph创新提出的基于进程级快照的冷启动加速解决方案，致力于在用户无感知（无需/少量进行代码适配）的前提下，帮助用户突破冷启动的性能瓶颈。本优化方案直接从应用初始化后的快照进行运行环境恢复，跳过复杂的框架、业务初始化阶段，从而显著降低 Java 应用的启动时延，实测性能提升达90%+。
**观测性能指标**
为了更好地支持用户使用函数，FunctionGraph提供了一系列指标供用户参考。一旦函数被调用，您可以在函数的监控页面和日志页面查看相应指标的变化，通过FunctionGraph函数的观测能力来进一步优化函数配置和函数代码。
目前，FunctionGraph提供的指标主要分为总览指标和函数指标。详细指标可参考[官方指标文档](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_0213.html)。
