高效开发与设计:提效Spring应用的运行效率和生产力
引言
现状和背景
Spring框架是广泛使用的Java开发框架之一,它提供了强大的功能和灵活性,但在大型应用中,由于Spring框架的复杂性和依赖关系,应用的启动时间和性能可能会受到影响。这可能导致开发过程中的迟缓和开发效率低下。优化Spring应用程序的启动速度和性能是一个重要的任务,通过分析和优化应用的初始化过程、减少不必要的依赖和组件加载、并利用异步初始化、懒加载等技术,可以显著改善应用的启动性能。这将帮助开发者提高开发效率、减少调试时间,并提供更好的用户体验。
线上的业务 jar 包基本上普遍比较庞大,动不动一个 jar 包几百 M,启动时间在10分钟级,拖慢了我们在故障时快速扩容的响应、以及本地开发调试效率。于是做了一些分析,看看 Spring 程序启动慢到底慢在哪里,如何去优化,目前的效果是大部分大型应用启动时间可以缩短 70%~80%。
主要有下面这些内容
- SpringBean 加载耗时 timeline 可视化分析()
- SpringBean 的可视化依赖分析()
- 应用未加载的jar包(Jar瘦身)()
- 应用启动过程线程wall clock火焰图()
重要性和影响
◦ 开发效率提高:较快的应用启动速度可以显著减少开发和调试的时间。开发人员能够更快地启动应用程序,进行功能测试和调试,从而提高开发效率和迭代速度。
◦ 部署和扩展效率提升:优化启动速度可以减少部署和扩展应用程序的时间和成本。快速启动的应用程序可以更快地响应负载变化,提高系统的可伸缩性和弹性。
◦ 资源利用率优化:通过减少初始化时间和优化资源加载,可以降低应用程序的内存和CPU占用率。这有助于提高服务器的利用率,并降低运行应用程序的成本。
分析工具
- Arthas:Arthas是一个开源的Java诊断工具,可以实时监控和诊断Java应用程序。它提供了丰富的命令和功能,用于分析应用程序的性能问题,包括启动过程中的资源消耗和加载时间。
- JVM Sandbox:JVM Sandbox是一种基于Java安全管理器的技术,用于隔离和限制Java应用程序的访问权限。它可以帮助减少启动时的资源消耗和加载时间,提高应用程序的启动速度。
- Async Profiler:Async Profiler是一个低开销的异步Java性能分析工具,用于收集和分析应用程序的性能数据。它可以帮助你找出启动过程中的性能瓶颈,以及其他影响启动速度的问题。
- 启动加速-异步初始化方法:异步初始化方法是一种启动加速的技术,通过将一些初始化任务异步执行,可以减少启动时间并提高应用程序的响应性。这可以通过使用线程池、异步框架或异步注解等方式来实现。
- Spring Boot Startup Report:Spring Boot Startup Report是一个用于生成Spring Boot应用程序启动报告的工具。它可以提供详细的启动过程信息,包括每个bean的加载时间、自动配置的耗时等,帮助你分析和优化启动过程。
- Jaeger UI: Jaeger UI是一个用于可视化和分析分布式追踪数据的工具。通过使用Jaeger UI,你可以监控和分析应用程序的启动过程,识别潜在的性能问题和瓶颈。
- Spring Startup Analyzer:Spring Startup Analyzer是一个用于采集Spring应用程序启动过程数据并生成交互式分析报告的工具。它的目标是帮助分析Spring应用程序的启动卡点,并支持Spring Bean的异步初始化,以减少优化Spring应用程序的启动时间。该工具支持在Linux、Mac和Windows操作系统上运行,并参考了spring-boot-startup-report实现其用户界面。使用Spring Startup Analyzer,可以收集应用程序的启动过程数据,并生成可视化的HTML报告。这个报告可以帮助你分析Spring应用程序的启动性能,并找出潜在的优化机会。
Spring Startup Analyzer优化方案
借助Spring startup analyzer的能力,我们以业务线的ARK项目为例,深入研究如何优化提效Spring项目的启动过程。下面我们先观察下ARK的基本启动情况:
启动概览
- Startup Time(s):启动时长
- Num of Bean:初始化的Bean数量
- Used/Total Jars:使用Jar数量/总量
- Unused/Total Jars:未使用Jar数量/总量
- ClassLoader Count:类加载器数量
Spring Bean初始化详情
- Name:一级name对应着Bean的名称
- Duration with children (ms) :Bean的引用加载时长
- Duration (ms) :Bean本身的加载时长
- Detail:包含类加载器、加载该Bean的线程信息(异步加载的话会有多个不同的)
SpringBean 加载耗时 timeline 可视化分析
这个观察项可以一直下探,直到Bean引用的最末级,可以看出每一级的加载时长
应用启动过程线程wall clock火焰图
如何看懂火焰图
y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。
x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。
火焰图就是看顶层的哪个函数占据的宽度最大。只要有"平顶"(plateaus),就表示该函数可能存在性能问题。
颜色没有特殊含义,因为火焰图表示的是 CPU 的繁忙程度,所以一般选择暖色调
火焰图总览
从总览图中可以看出,有三个入口函数占用百分比较大,下面分别看一下
火焰局部图1
这部分火焰图可以看出,springfox在启动过程做了很多初始化,占了大量时间,对于不需要该功能的项目,可以直接下掉
火焰局部图2
了解下spring bean 的初始化过程
从这个图中可以看出,bean的创建过程也占了很多时间
火焰局部图3
从这个图中可以看出,注册BeanPostProcessor也耗费了大量时间
应用未加载的jar包(Jar瘦身)
这一个观察项可以搜集到项目启动完之后,没有用到的Jar包
实施与优化效果
操作步骤和配置项
安装Spring Startup Analyzer
手动安装
点击realease下载最新版tar.gz包
新建文件夹,并解压
linux/mac系统可以考虑使用以下命令:
mkdir -p ${HOME}/spring-startup-analyzercd 下载路径
tar -zxvf spring-startup-analyzer.tar.gz -C 安装路径/spring-startup-analyzer
脚本安装(linux/mac)
curl -sS https://raw.githubusercontent.com/linyimin0812/spring-startup-analyzer/main/bin/install.sh | sh
脚本默认安装路径:$HOME/spring-startup-analyzer
应用启动
spring-startup-analyzer是以agent的方式启动的,所以在启动命令中添加参数-javaagent:安装路径/spring-startup-analyzer/lib/spring-profiler-agent.jar
即可。
- 以java命令行的方式启动应用,则在命令行中添加参数,例如:
java -javaagent:/Users/runner/spring-startup-analyzer/lib/spring-profiler-agent.jar \
-Dproject.name=mac-demo \
-Dspring-startup-analyzer.admin.http.server.port=8066 \
-jar /Users/runner/spring-startup-analyzer/ARK.jar
- IDEA中启动,则需要在VM options选项中添加:
日志文件路径:安装路径/spring-startup-analyzer/logs
- startup.log: 启动过程中的日志
- transform.log: 被re-transform的类/方法信息
应用启动完成后会在console和startup.log文件中输出======= spring-startup-analyzer finished, click http://localhost:xxxx to visit details. ======
,可以通过此输出来判断采集是否完成。
启动时间和性能改善情况
优化之前
预发平均启动10分钟,本地无法启动,每次需求需要提交到预发环境验证,开发和发版周期比较长,且预发环境连接的生产库,不能随便造数。项目引用585个jar,其中有337个jar没用到。
慢bean分析
分析可以看到,耗时排名前面的接口都是jsf相关的加载,还有一个es相关的bean。
功能路径:Details of Method Invoke --> AbstractAutowireCapableBeanFactory.createBean
jsf启动优化
注:index=“注册中心地址”中的“注册中心地址“做了匿名,在具体场景查看自己代码中的配置
jsf的生产者的注册中心在启动的时候,会拉取一批ip,不断尝试注册jsf,在办公环境这些ip无法访问,导致启动过程一直重试
<!-- 预发、生产的注册中心 -->
<jsf:registry id="jsfRegistry" protocol="jsfRegistry" index="注册中心地址"/>
在本机host里面增加jsf发布地址的host配置,下面*...* 在使用的时候替换成自己的,可以 ping test.注册中心地址 获取。“注册中心地址” 替换成上面index后面的地址
*.*.*.* 注册中心地址
再次启动项目,时长来到185s
开启Bean懒加载
将ES的Bean初始化进行懒加载,以及开启全局懒加载,时长来到131s;
全局懒加载:
1、根据spring版本的不同,开启全局懒加载的方式可能会不相同
2、不建议生产环境开启全局懒加载,因为基本上我们的服务都是部署在k8s上的,有可能服务在伸缩的时候,在访问量大的时候,由于懒加载的配置,服务快速启动成功了,会返回给docker容器服务已经准备就绪状态,导致k8s把流量分给该服务,导致预想不到的问题。
Jar瘦身
对于应用未使用的jar包,可以谨慎剔除,在剔除的时候一个一个下,每下一个都要重复编译和启动验证是否会对项目造成影响,这是一个持续和长期的过程,Jar瘦身不仅对启动时长有收益,而且对编译提效很明显,减少了大量的Jar复制过程
最终效果
做完上述优化之后:
- 本地能够启动和debug项目,这对开发人员来说有极大的提效。
- 预发使用该方案进行优化之后,能够缩短项目编译以及发布的时间,对于快速验证和迭代需求有极大提效。
- 整体启动效率提升70%~80%。
- 在intel芯片电脑,启动速度在2min11s。
- 在m1芯片的电脑,速度会更快,大概启动时间在90s左右。
- 使用该思路,可以优化大部分spring以及spring boot项目,建议定期做一轮这种排查和优化。
优化关键点和方法
- 去除未使用的jar包:定位未使用的jar包。通过分析和整理项目依赖,可以将这些未使用的jar包从应用中移除,减少编译、启动时间和资源消耗。
- 优化慢速的Bean初始化:找到启动耗时较长的Bean。可以考虑对这些接口和Bean进行优化,例如使用延迟加载或异步加载的方式,以减少启动时的耗时。
- 取消不需要的发布:对于本地开发环境而言,如果不需要发布jsf接口,可以在本地取消这部分的发布,以节省启动时间。
- 开启全局懒加载:通过开启全局懒加载,可以延迟加载一些不必要的组件和资源,从而减少启动时间。确保在需要使用时才进行加载。
- 拆分大型组件:定位加载时间较长的组件,可以考虑将其拆分成多个组件,并在启动时只加载需要的部分。这样可以减少启动时的加载时间和资源消耗。
- 使用性能分析工具:结合之前提到的性能分析工具,如Spring Startup Analyzer、Java Profiler、VisualVM等,对应用进行性能分析。通过监测和分析应用的性能数据,可以找到性能瓶颈,并针对性地进行优化。
- 定期进行代码优化和重构:定期审查和优化代码,识别和消除潜在的性能问题。使用优化的算法和数据结构,减少不必要的计算和循环,优化数据库查询等,以提高应用的性能。
- 使用缓存机制:合理地使用缓存来减少对数据库或其他资源的频繁访问。通过缓存常用数据或计算结果,可以显著提升应用的响应速度和性能。
- 并行化处理:如果有一些独立的任务可以并行处理,可以考虑使用多线程或异步机制来提高处理速度和效率。
信息补充
oracle jdk8下载地址
https://www.oracle.com/java/technologies/downloads/#java8-mac
oracle登录账号
请联系作者提供免费账号
本地redis安装
https://redis.io/docs/install/install-redis/install-redis-on-windows/
spring-startup-analyzer启动分析工具
https://github.com/linyimin0812/spring-startup-analyzer/blob/main/README_ZH.md
作者:京东健康 梁灿
来源:京东云开发者社区 转载请注明来源
高效开发与设计:提效Spring应用的运行效率和生产力的更多相关文章
- 利用低代码优化人力资源配置,为软件开发降本提效 ZT
低代码 是一种主要应用于企业信息化领域的快速开发技术.借助低代码,开发者无需编码即可生成企业应用的常见功能,少量编码能开发出更多扩展功能.有了低代码技术,IT团队甚至业务团队都可以参与到编写应用程序当 ...
- Struts2、Spring、Hibernate 高效开发的最佳实践(转载)
Struts2.Spring.Hibernate 高效开发的最佳实践 Struts2.Spring.Hibernate(SSH)是最常用的 Java EE Web 组件层的开发技术搭配,网络中和许多 ...
- Spring Boot 2.X(十九):集成 mybatis-plus 高效开发
前言 之前介绍了 SpringBoot 整合 Mybatis 实现数据库的增删改查操作,分别给出了 xml 和注解两种实现 mapper 接口的方式:虽然注解方式干掉了 xml 文件,但是使用起来并不 ...
- 阿里巴巴如何进行测试提效 | 阿里巴巴DevOps实践指南
编者按:本文源自阿里云云效团队出品的<阿里巴巴DevOps实践指南>,扫描上方二维码或前往:https://developer.aliyun.com/topic/devops,下载完整版电 ...
- 声网Agora发布教育信息化解决方案 助力教育公平提效
4月23日-25日,由中国教育装备行业协会主办的第79届教育装备展在厦门国际会展中心举办.作为赋能教育信息化的实时互动PaaS服务商,声网Agora应邀参会.展会现场,声网展示了基于实时音视频互动能力 ...
- .Net 高效开发之不可错过的实用工具(转)
.Net 高效开发之不可错过的实用工具(转) 本文摘自: http://www.cnblogs.com/powertoolsteam/p/5240908.html#3372237 Visual Stu ...
- WPF Multi-Touch 开发:高效开发模式
原文 WPF Multi-Touch 开发:高效开发模式 在前几篇文章中已经介绍了触屏操作的多种模式,并对其开发方式也有了进一步了解.细心的朋友应该会发现在上一篇文章中,如果拖动图片过快它会因惯性效果 ...
- Net 高效开发
Net 高效开发之不可错过的实用工具 工欲善其事,必先利其器,没有好的工具,怎么能高效的开发出高质量的代码呢?本文为各ASP.NET 开发者介绍一些高效实用的工具,涉及SQL 管理,VS插件,内存 ...
- .NET 高效开发之不可错过的实用工具(第一的当然是ReSharper插件)
工欲善其事,必先利其器,没有好的工具,怎么能高效的开发出高质量的代码呢?本文为 ASP.NET 开发者介绍一些高效实用的工具,包括 SQL 管理,VS插件,内存管理,诊断工具等,涉及开发过程的各个环节 ...
- NET 高效开发之不可错过的实用工具(第一的当然是ReSharper插件)
工欲善其事,必先利其器,没有好的工具,怎么能高效的开发出高质量的代码呢?本文为 ASP.NET 开发者介绍一些高效实用的工具,包括 SQL 管理,VS插件,内存管理,诊断工具等,涉及开发过程的各个环节 ...
随机推荐
- Vue报错Custom elements in iteration require 'v-bind:key' directives."错误解决
错误代码 <swiper> <swiper-item v-for="item in banners"> <a :href="item.lin ...
- Django日志输出
# 自定义日志输出信息 LOGGING = { 'version': 1, 'disable_existing_loggers': True, 'formatters': { 'standard': ...
- Python3入门基础教程
引:此文是自己学习python过程中的笔记和总结,适合有语言基础的人快速了解python3和没基础的作为学习的大纲,了解学习的方向.知识点:笔记是从多本书和视频上学习后的整合版. (一)初识pytho ...
- 青少年CTF平台-Web-Robots
题目信息 题目名称:Robots 题目描述:昨天十三年社团讲课,讲了Robots.txt的作用,小刚上课没有认真听课正在着急,你能不能帮帮忙? 题目难度:一颗星 解题过程 访问题目链接 在这里插入图片 ...
- 【技术积累】Linux中的命令行【理论篇】【十】
bunzip2 命令说明 bunzip2命令是Linux系统中的一个用于解压缩文件的命令.它可以解压缩使用bzip2算法压缩的文件,将其恢复为原始的未压缩文件. 命令介绍 bunzip2命令的语法如下 ...
- 《Web安全基础》03. SQL 注入
@ 目录 1:简要 SQL 注入 2:MySQL 注入 2.1:信息获取 2.2:跨库攻击 2.3:文件读写 2.4:常见防护 3:注入方法 3.1:类型方法明确 3.2:盲注 3.3:编码 3.4: ...
- 《小白WEB安全入门》01. 扫盲篇
@ 目录 基础知识 什么是WEB 什么是前端 什么是后端 什么是数据库 什么是协议 什么是WEB安全 什么是服务器 什么是IP地址.端口 什么是局域网.广域网.内网.外网 什么是URL 什么是MAC地 ...
- 《CTFshow-Web入门》01. Web 1~10
@ 目录 web1 题解 web2 题解 web3 题解 web4 题解 web5 题解 原理 web6 题解 原理 web7 题解 web8 题解 web9 题解 原理 web10 题解 ctf - ...
- KRPANO资源分析工具下载720THINK全景图
提示:目前分析工具中的全景图下载功能将被极速全景图下载大师替代,相比分析工具,极速全景图下载大师支持更多的网站(包括各类KRPano全景网站,和百度街景) 详细可以查看如下的链接: 极速全景图下载大师 ...
- 面试官:说一下 MyBatis 缓存机制?
MyBatis 的缓存机制属于本地缓存,适用于单机系统,它的作用是减少数据库的查询次数,提高系统性能. MyBaits 中包含两级本地缓存: 一级缓存:SqlSession 级别的,是 MyBatis ...