你的Spring应用启动很慢?不妨试试这个工具!
睡不着闲逛,在GitHub上看到一个挺实用的开源项目:Spring Startup Analyzer。
从项目名称中就大概能猜到,这是一个分析Spring应用启动过程的工具。Spring Startup Analyzer通过采集Spring应用启动过程的数据,进而生成一个交互式的分析报告,帮助用户发现Spring应用启动慢的位置。
同时,Spring Startup Analyzer还提供了Spring Bean异步初始化的工具,来帮助开发者加快Spring应用的启动时间。
下面一起来看看其提供的强大功能。
分析能力
我们可以先从该项目中给出HTML样例报告来看看它所提供的分析功能。感兴趣的可以通过下面链接访问:
把报告内容的细节部分都收起来,可以看到如下图所示的内容:

主要有六个部分:
- 启动的统计数据。其中包括:启动时间、Bean的数量、使用/总共的JAR包数量、未使用/总共的JAR包数量、ClassLoader数量

- Spring Bean初始化数据。这里采集了每个Spring Bean的初始化时间及其细节内容

- Bean初始化时间线。通过时间线的方式,清晰地展现了Spring应用启动时候,各个Bean的顺序关系以及时间消耗

- 方法调用的详细信息。这里统计了每个方法的调用时间、总时间开销和每次调用的平均时间

点开之后,还能看到具体每次调用时候的时间开销和一些调用细节:

- 启动后未使用的JAR。列出了所有Spring应用启动后没有使用的jar包,可以有效的帮助你清理不需要的依赖,为应用瘦身

- 应用启动过程的线程火焰图

如何使用
通过上面的介绍,相信你已经了解该工具的强大之处了。接下来就可以通过下面的方法尝试分析一下自己的应用吧:
第一步:从里面的链接中下载最新的安装包
https://github.com/linyimin0812/spring-startup-analyzer/tags
第二步:解压下载的安装包,记住解压后的路径,下面一步要用
第三步:编辑Spring Boot的启动参数,包括:
- 该工具采用agent的方式启动,所以要添加参数
-javaagent:$HOME/spring-startup-analyzer/lib/spring-profiler-agent.jar,这里$HOME代表以前的解压路径,记得根据上面解压后的路径编辑这个参数 - 配置分析工具的参数,这里根据自己需要添加即可,比如可以配置超时时间30分钟:
-Dspring-startup-analyzer.app.health.check.timeout=30,其他可配置项如下表,你可以工具自己应用的情况去修改:

第四步:查看该工具的日志,可以通过$HOME/spring-startup-analyzer/logs路径,这里$HOME代表以前的解压路径,日志文件的类别为:
- startup.log: 启动过程中的日志
- transform.log: 被re-transform的类/方法信息
另外,该工具还支持自定义扩展,这里DD没试过,就不具体介绍了。感兴趣的童鞋可以根据文档去试试。
启动优化
这里提到了一个启动加速的优化思路,就是把一些耗时的Bean初始化改成异步就能实现。该项目提供了Bean的异步初始化工具,也非常好用,只需要下面几步就能完成。
第一步:引入依赖
<dependency>
<groupId>io.github.linyimin0812</groupId>
<artifactId>spring-async-bean-starter</artifactId>
<version>2.0.2</version>
</dependency>
第二步:配置参数
# 异步化的Bean可能在Spring Bean初始化顺序的末尾,导致异步优化效果不佳,打开配置优先加载异步化的Bean
spring-startup-analyzer.boost.spring.async.bean-priority-load-enable=true
# 指定异步的Bean名称
spring-startup-analyzer.boost.spring.async.bean-names=testBean,testComponent
# 执行异步化Bean初始化方法线程池的核心线程数
spring-startup-analyzer.boost.spring.async.init-bean-thread-pool-core-size=8
# 执行异步化Bean初始化方法线程池的最大线程数
spring-startup-analyzer.boost.spring.async.init-bean-thread-pool-max-size=8
第三步:检查Bean是否异步初始化。查看日志$HOME/spring-startup-analyzer/logs/startup.log文件,对于异步执行初始化的方法,会按照以下格式写一条日志:
async-init-bean, beanName: ${beanName}, async init method: ${initMethodName}
但是,作者在文档中也提到了,异步并不是万能的,你还需要注意以下这几点:
- 应该优先从代码层面优化初始化时间长的Bean,从根本上解决Bean初始化耗时长问题
- 对于二方包/三方包中初始化耗时长的Bean(无法进行代码优化)再考虑Bean的异步化
- 对于不被依赖的Bean可以放心进行异步化,可以通过各个Bean加载耗时中的Root Bean判断Bean是否被其他Bean依赖
- 对于被依赖的Bean需要小心分析,在应用启动过程中不能其他Bean被调用,否则可能会存在问题
好了,今天的学习就到这里!如果您学习过程中如遇困难?可以加入我们超高质量的Spring技术交流群,参与交流与讨论,更好的学习与进步!更多Spring Boot教程可以点击直达!,欢迎收藏与转发支持!
最后,奉上项目地址:https://github.com/linyimin0812/spring-startup-analyzer
欢迎关注我的公众号:程序猿DD。第一时间了解前沿行业消息、分享深度技术干货、获取优质学习资源
你的Spring应用启动很慢?不妨试试这个工具!的更多相关文章
- Spring Boot -- 启动彩蛋
使用Spring Boot启动的jar包总是会显示一个Spring的图标: . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\_ ...
- Spring Boot 启动原理分析
https://yq.aliyun.com/articles/6056 转 在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启 ...
- Spring Boot 启动(四) EnvironmentPostProcessor
Spring Boot 启动(四) EnvironmentPostProcessor Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698. ...
- Spring Boot 启动(二) 配置详解
Spring Boot 启动(二) 配置详解 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring Boot 配置 ...
- Spring Boot 启动(二) Environment 加载
Spring Boot 启动(二) Environment 加载 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 上一节中 ...
- Spring Boot 启动(一) SpringApplication 分析
Spring Boot 启动(一) SpringApplication 分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html ...
- 转:spring的启动过程-spring和springMVC父子容器的原理
要想很好理解这三个上下文的关系,需要先熟悉spring是怎样在web容器中启动起来的.spring的启动过程其实就是其IoC容器的启动过程,对于web程序,IoC容器启动过程即是建立上下文的过程. s ...
- [Spring Boot] Spring Boot启动过程源码分析
关于Spring Boot,已经有很多介绍其如何使用的文章了,本文从源代码(基于Spring-boot 1.5.6)的角度来看看Spring Boot的启动过程到底是怎么样的,为何以往纷繁复杂的配置到 ...
- Spring Boot启动过程(三)
我已经很精简了,两篇(Spring Boot启动过程(一).pring Boot启动过程(二))依然没写完,接着来. refreshContext之后的方法是afterRefresh,这名字起的真.. ...
- Spring Boot启动原理解析
Spring Boot启动原理解析http://www.cnblogs.com/moonandstar08/p/6550758.html 前言 前面几章我们见识了SpringBoot为我们做的自动配置 ...
随机推荐
- 尝试CentOS8---部署集群(生产环境7.9为好)
一.LVS集群简介 什么是集群 通过网络将很多服务器集中起来,提供同一种服务,在客户端看来就像是只有一个服务器 二.LVS-NAT集群 1.环境准备 启动3台虚拟机,禁用selinux和firewal ...
- 「学习笔记」重修 FHQ-treap
无旋 treap 的操作方式使得它天生支持维护序列.可持久化等特性. 无旋 treap 又称分裂合并 treap.它仅有两种核心操作,即为 分裂 与 合并.通过这两种操作,在很多情况下可以比旋转 tr ...
- Node工程的依赖包管理方式
作者:京东零售 陈震 在前端工程化中,JavaScript 依赖包管理是非常重要的一环.依赖包通常是项目所依赖的第三方库.工具和框架等资源,它们能够帮助我们减少重复开发.提高效率并且确保项目可以正确的 ...
- Java实现平衡二叉搜索树(AVL树)
上一篇实现了二叉搜索树,本章对二叉搜索树进行改造使之成为平衡二叉搜索树(Balanced Binary Search Tree). 不平衡的二叉搜索树在极端情况下很容易退变成链表,与新增/删除/查找时 ...
- react中子组件给父组件传值
组件间通信: React中,数据是从上向下流动的,也就是一个父组件可以把它的 state/props通过props传递给它的子组件,但是子组件,不能修改props,如果组件需要修改父组件中的数据,则 ...
- 魔王语言问题c语言实现及思路求解
文章目录 问题描述及需求分析 需求分析 问题分析及实现路线(队列+栈) 结构体核心代码 队列核心代码 入队 出队 栈的核心代码 入栈 出栈 全部代码 单向循环队列和栈(改变B的对应密码) 总结 问题描 ...
- Layui+dtree实现左边分类列表,右边数据列表
效果如下 代码实现 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...
- SDK日志上传性能优化
问题描述 在SDK初始化时,会在init方法中开启一个倒计时,在5s倒计时结束后使用子线程将本地保存的历史日志信息上传到后台. 因业务需要,在日志在发送上传前,对日志数据上传时需要对日志数据做编码和特 ...
- 2020-09-15:java里的wait()和sleep()的区别有哪些?
福哥答案2020-09-15:#福大大架构师每日一题# 1.线程状态.wait()的线程状态是TimedWaiting和Waiting.sleep()的线程状态是Waiting.2.指定时间.wait ...
- 2022-09-16:以下go语言代码输出什么?A:101;B:100;C:1;D:2。 package main import ( “fmt“ ) type MS struct {
2022-09-16:以下go语言代码输出什么?A:101:B:100:C:1:D:2. package main import ( "fmt" ) type MS struct ...