Spring Boot Serverless 实战系列 | 性能调优

本文涉及的产品
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
函数计算FC,每月15万CU 3个月
简介: Spring Boot Serverless 实战系列第四篇来啦,本文将向大家介绍如何对 Serverless 应用进行性能调优。

SpringBoot 是基于 Java Spring 框架的套件,它预装了 Spring 的一系列组件,让开发者只需要很少的配置就可以创建独立运行的应用程序。在云原生的世界,有大量的平台可以运行 SpringBoot 应用,例如虚拟机,容器等。但其中最有吸引力的,是以 Serverless 的方式运行 SpringBoot 应用。我将通过一系列文章,从架构,部署,监控、性能、安全等5个方面来分析 Serverless 平台运行 SpringBoot 应用的优劣。为了让分析更有代表性,我选择了 github 上 star 数超过 50k 的电商应用 mall 作为示例。这是系列文章的第四篇, 向大家展示如何对 Serverless 应用性能调优。


实例启动速度优化


在之前的文章实战教程中,相信大家都感受到 Serverless 的便捷之美,只需上传代码包和镜像就能够轻松上线一个弹性高可用的 Web 应用。但是它仍存在首次启动“冷启动延时”的问题,Mall 应用实例的启动大约 30 秒左右,用户会感受较长时间的冷启动延时,在这个“即时时代”应用程序响应慢多少会有些瑕不掩瑜。(“冷启动”是指函数服务于特定调用请求时的状态,当一段时间没有请求后,Serverless 平台则会回收函数实例;等到下一次再有请求时,系统会再次实时拉起实例,这个过程称之为冷启动。)

在优化冷启动之前,我们先要分析清楚冷启动各个阶段的耗时。首先在函数计算(FC) 控制台的服务配置界面,开启链路追踪功能。



对 mall-admin 服务发起请求,成功后查看 FC 控制台,我们能够看到相应的请求信息。注意关闭“仅查看函数错误”,这样才会显示所有请求。指标监控和调用链路数据收集会存在一定延时,如果没有显示,请等待一会再刷新。找到冷启动标记的请求,点击 “更多” 下的 “请求详情”。



调用链路会显示冷启动各个环节的耗时。冷启动包含以下几个环节:


  • 代码准备(PrepareCode):主要是下载代码包或者镜像。由于我们已经启用了镜像加速功能,不需要下载全部的镜像,因此这一步的延时非常短。
  • 运行时初始化(RuntimeInitialization):从启动函数开始,到函数计算(FC)系统探测到应用端口就绪为止。这中间包含了应用启动时间。在命令行执行 s mall-admin logs 查看相应的日志时间,我们也能看到 Spring Boot 应用的启动需要花大量的时间。
  • 应用初始化(Initialization):函数计算提供了 Initializer 接口,用户可以将一些初始化逻辑放在 initializer 中执行。
  • 调用延时(Invocation):处理请求的延时,这个延时非常短。



从上述链路追踪图来看,实例启动时间是瓶颈,我们可以采取多种方式来优化。


1.1. 使用预留实例


Java 类应用普遍启动较慢。应用在初始化时,也需要和很多外部服务交互,耗时较长。这类流程是业务逻辑需要的,很难优化延时。因此函数计算提供了预留实例功能。预留实例的起停由用户自己控制,没有请求也会常驻在那,因此不会有冷启动的问题,当然用户需要为整个实例的运行付费,即便实例没有处理任何请求。


在函数计算控制台,我们可以在“弹性伸缩”页面为函数设置预留实例。



用户在控制台中配置最小和最大实例数。平台会预留最小实例数目的实例,最大实例是指该函数下实例的上限。用户也可以设置定时预留和按指标预留的规则。



创建预留规则后,系统就会创建预留实例。当预留实例就绪后,我们再访问函数就不会有冷启动。



1.2. 优化实例启动速度


延迟初始化


在 Spring Boot 2.2 及更高版本中,可以开启一个全局延迟初始化标志。这将提高启动速度,但代价是第一个请求的延迟时间可能变长,因为需要等待组件首次初始化。


可在 s.yaml 中为相关应用配置以下环境变量


SPRING_MAIN_LAZY_INITIATIALIZATION=true


关闭优化编译器


默认情况下,JVM 有多个阶段的 JIT 编译。虽然这些阶段可以逐渐提高应用的效率,但它们也会增加内存使用的开销,并增加启动时间。对于短期运行的 Serverless 应用,请考虑关闭此优化,以牺牲长期效率换取更短的启动时间。


可在 s.yaml 中为相关应用配置以下环境变量:


JAVA_TOOL_OPTIONS="-XX:+TieredCompilation -XX:TieredStopAtLevel=1"


s.yaml 中设置环境变量示例:


如下图所示,对 mall-admin 函数配置环境变量。然后执行 sudo -E s mall-admin deploy 部署。



登录实例检查环境变量是否配置正确


在控制台函数详情页的请求列表中找到对应的请求,点击更多中的“实例详情链接”。



在实例详情页中点击“登录实例”。



在 shell 界面中执行 echo 命令,查看对应的环境变量是否设置正确。


注意:对于非预留实例,一段时间没有请求后,函数计算系统会自动回收实例。此时无法再登入实例(上面的实例详情页面中的登录实例按钮会变灰)。所以请执行调用后,在实例被回收之前尽快登录。



配置合理的实例参数


当我们选择了应用实例规格,比如 2C4G 或者 4C8G,接下来我们希望知道一个实例处理多少请求可以既能充分利用资源又能够保证性能。当处理的请求超过一个限制后,系统能够快速弹出实例,保证应用性能平滑。如何度量实例过载有多个维度,例如 qps 超过一定阈值,或者实例 CPU/Memory/Network/Load 等指标超过阈值等等。函数计算使用实例并发度(Instance Concurrency)来作为实例负载的度量和实例伸缩的依据。实例并发度(Instance Concurrency)是指一个实例能同时执行的请求数。例如将实例并发度设置为 20,则意味着一个实例在任意时刻最大能同时执行 20 个请求。

注意:请区分实例并发度和 QPS 的区别。

使用实例并发度来度量负载有如下优势:

  • 系统能够迅速统计实例并发度指标值进行扩缩容。CPU/Memory/Network/Load 等实例级别的指标通常是后台统计,需要花费数十秒的指标统计后才能进行伸缩,难以满足在线应用的弹性伸缩要求。
  • 在各种条件下,实例并发度指标都能够稳定的反映系统负载高低。如果以请求延时作为指标,系统难以区分是实例过载导致延时变大,还是下游服务成为瓶颈导致延时变大。例如一个典型的 Web 应用,通常会访问 MySQL 数据库。如果数据库成为瓶颈,请求延时变大,此时扩容不但毫无意义,而且会压垮数据库,让情况更加恶化。QPS 和请求延时相关,也会有上述问题。


实例并发度作为伸缩依据虽然有上述优点,但用户常常并不知道该设置多大的实例并发度。我推荐按照下述流程确定合理的并发度:

  1. 将应用函数的最大实例数设置为1,确保压测到单个实例的性能。
  2. 使用负载压测工具对应用进行压测,查看 tps 和请求延时等指标
  3. 逐步调大实例并发度,如果性能仍然良好,则继续调大;如果性能不符合预期,则调小并发度。
相关实践学习
【文生图】一键部署Stable Diffusion基于函数计算
本实验教你如何在函数计算FC上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。函数计算提供一定的免费额度供用户使用。本实验答疑钉钉群:29290019867
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
相关文章
|
2月前
|
关系型数据库 MySQL Serverless
探索PolarDB MySQL版:Serverless数据库的灵活性与性能
本文介绍了个人开发者对阿里云PolarDB MySQL版,特别是其Serverless特性的详细评测体验。评测涵盖了产品初体验、性能观测、Serverless特性深度评测及成本效益分析等方面。尽管试用过程中遇到一些小问题,但总体而言,PolarDB MySQL版表现出色,提供了高性能、高可用性和灵活的资源管理,是个人开发者和企业用户的优秀选择。
|
4天前
|
监控 前端开发 Java
Java SpringBoot –性能分析与调优
Java SpringBoot –性能分析与调优
|
24天前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
39 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
12天前
|
自然语言处理 Java API
Spring Boot 接入大模型实战:通义千问赋能智能应用快速构建
【10月更文挑战第23天】在人工智能(AI)技术飞速发展的今天,大模型如通义千问(阿里云推出的生成式对话引擎)等已成为推动智能应用创新的重要力量。然而,对于许多开发者而言,如何高效、便捷地接入这些大模型并构建出功能丰富的智能应用仍是一个挑战。
57 6
|
16天前
|
缓存 NoSQL Java
Spring Boot与Redis:整合与实战
【10月更文挑战第15天】本文介绍了如何在Spring Boot项目中整合Redis,通过一个电商商品推荐系统的案例,详细展示了从添加依赖、配置连接信息到创建配置类的具体步骤。实战部分演示了如何利用Redis缓存提高系统响应速度,减少数据库访问压力,从而提升用户体验。
42 2
|
2月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
348 37
|
28天前
|
Java 数据库连接 Spring
【2021Spring编程实战笔记】Spring开发分享~(下)
【2021Spring编程实战笔记】Spring开发分享~(下)
25 1
|
1月前
|
缓存 NoSQL Java
Springboot自定义注解+aop实现redis自动清除缓存功能
通过上述步骤,我们不仅实现了一个高度灵活的缓存管理机制,还保证了代码的整洁与可维护性。自定义注解与AOP的结合,让缓存清除逻辑与业务逻辑分离,便于未来的扩展和修改。这种设计模式非常适合需要频繁更新缓存的应用场景,大大提高了开发效率和系统的响应速度。
46 2
|
18天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
46 0
|
2月前
|
消息中间件 弹性计算 关系型数据库
体验函数计算:高效处理多媒体文件的真实感受与实战总结
该方案在引导和文档方面做得较为详尽,仅在事件驱动机制部分略显简略。部署和代码示例实用,但需注意内存配置以避免超时。使用体验方面,函数计算表现出色,尤其在高并发场景下,显著提升了应用稳定性和成本效益。云产品如OSS、MNS等与函数计算配合流畅,ECS和RDS表现稳健。总体而言,这套方案弹性好、成本低,特别适合应对高并发或流量不确定的场景,值得推荐。
66 24

热门文章

最新文章

相关产品

  • 函数计算