一、 简介
项目优化,首先要定位慢在哪里。记录下几个方法。官方的ApplicationStartup的实现类,BufferingApplicationStartup,FlightRecorderApplicationStartup,以及第三方利用ApplicationStartup的工具。对比下来,直接用工具更加直观,也更方便。
二、官方实现的ApplicationStartup 接口
Spring Boot 提供了BufferingApplicationStartup、FlightRecorderApplicationStartup两种实现,也支持自定义实现该接口。
2.1 BufferingApplicationStartup
记录启动时各阶段的耗时。
使用方法
- 修改启动类
publicstaticvoidmain(String[]args){SpringApplicationapp=newSpringApplication(SpringbootApplication.class);// 核心:设置缓冲区大小(比如记录最近 4096 个步骤)app.setApplicationStartup(newBufferingApplicationStartup(4096));app.run(args);}- 打印日志
@AutowiredprivateBufferingApplicationStartupstartup;@GetMapping("/an")publicvoidgetAnalyzer(){@AutowiredprivateBufferingApplicationStartupstartup;@GetMapping("/an")publicvoidgetAnalyzer(){StartupTimelinetimeline=startup.getBufferedTimeline();// 2. 计算总耗时System.out.println("应用总启动耗时: "+timeline.getStartTime().toString());// 3. 遍历具体的启动步骤(找出最耗时的步骤)timeline.getEvents().forEach(event->{longduration=event.getDuration().toMillis();StartupStepstartupStep=event.getStartupStep();// 只打印耗时超过 600ms 的步骤if(duration>100){if("spring.beans.instantiate".equals(startupStep.getName())){for(StartupStep.Tagtag:startupStep.getTags()){if("beanName".equals(tag.getKey())){System.out.println("耗时步骤: "+startupStep.getName()+":"+tag.getValue()+" 耗时: "+duration+" ms");}}}else{System.out.println("耗时步骤: "+startupStep.getName()+" 耗时: "+duration+" ms");}}});}}- 日志如下
从日志中可以看到关键步骤的耗时,以及每个 bean 的创建时间。
2.2 FlightRecorderApplicationStartup
记录每个bean创建的细节
使用方法
1、修改启动类
publicstaticvoidmain(String[]args){SpringApplicationapp=newSpringApplication(SpringbootApplication.class);// 核心:设置缓冲区大小(比如记录最近 4096 个步骤)app.setApplicationStartup(newFlightRecorderApplicationStartup());app.run(args);}2、添加jvm参数
java -XX:StartFlightRecording:filename=recording.jfr,duration=60s -jar demo.jar
3、启动项目,启动成功会本地会生成文件 recording.jfr
4、查看内容
为什么没有内容,我也不知道。
试了几个不同方法都不行。谁知道的教教我。
三、自定义ApplicationStartup
无,有这个功能。但是不需要会。已经有现成的工具了,下面介绍
四、外部工具
目前只了解到spring-startup-analyzer,后面收到再补充
4.1 spring-startup-analyzer
它的核心思路是在启动过程中挂载自定义ApplicationStartup实现,收集所有StartupStep的耗时数据,再在启动结束后汇总成可视化报告,因此对业务代码基本无侵入。
相比 Spring Boot 自带的ApplicationStartup,spring-startup-analyzer 提供的信息更全面:不仅能看单个 bean 的创建时间,还能做数量统计、方法耗时统计和 jar 包加载统计,适合排查「启动慢到底慢在哪」这类问题.
使用方法
- 下载最新版本的 jar 包(或直接 clone 源码后本地打包)。
下载链接:https://gitcode.com/gh_mirrors/sp/spring-startup-analyzer - 解压后有五个文件夹,应用在lib,log有启动日志
- 在启动命令中通过
-javaagent挂载该 agent,
java-javaagent:/path/to/spring-startup-analyzer.jar\-jaryour-application.jaridel 中可在vm option中添加
5. 应用启动完成后,agent 会自动生成分析报告,并在控制台打印报告文件的访问地址
6. 打开报告页面,即可查看各阶段耗时、bean 创建明细、方法调用统计和 jar 加载情况。
页面说明
1、指标数据,总耗时,总bean数,总jar包,引入未使用的包,类加载器(不知道干啥的)
2、bean耗时排序,展示耗时最长的bean,支持过滤。
3、启动时序图
3、调用方法统计
方法名,次数,耗时,占比
展开详情
一些其他配置
-Dspring-startup-analyzer.app.health.check.endpoints=http://127.0.0.1:8081/actuator/health
手动指定健康节点,
总结
工具好用一点,
能找到最慢的几个类esbAppHeadResourceResolver
braveHttpServerHandler,需要优化的话可以重点关注
杂记
esbAppHeadResourceResolver 看了下代码,会重新扫描项目下包,找到配置了对应注解的类。缓存到内存中。时间几乎花在重新扫描上。可以的话,这个地方能优化下。