Spring应用启动很慢?试试这个工具

news2024/11/19 9:36:00

前段时间搞应用启动优化的时候参考了这篇文章的很多观点,并基于此开发了此工具——spring-startup-analyzer。这是一个分析Spring应用启动过程的工具,通过采集Spring应用启动过程数据,生成交互式分析报告,用于分析Spring应用启动卡点。同时还提供了一些工具来帮助开发者加快Spring应用的启动时间。下面详细介绍一下其提供的能力。

1. 能力介绍


1.1 分析能力

首先通过项目给出的HTML样例报告来看看此工具提供的分析功能。感兴趣的可以通过下面的链接访问:

  • hokage-20230618000928-192.168.0.101-analyzer.html

把报告内容的细节部分收起来,可以看到如下图所示的内容:

image.png

主要包含6部分:

  • 启动的统计数据。其中包括:启动时间、Bean的数量、使用/总共的jar包数量、未使用/总共的jar包数量及ClassLoader数量;

image.png

  • Spring Bean初始化数据,采集了每个Spring Bean初始化时间及其详细内容;

image.png

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

image.png

  • 方法调用详细信息(可配置)。这里统计了方法的调用时间、总时间开销及每次调用平均时间

image.png

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

image.png

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

image.png

  • Spring应用启动过程主线程火焰图。提供更详细的信息用于分析应用启动卡点

image.png

1.2 启动优化


提供了生产环境和日常/预发环境两种场景的优化,对于生产环境,提供Spring Bean异步加载工具,将耗时的Bean初始化方法异步化(参考SOFABoot的异步初始化方法实现)。对于日常/预发环境,提供命令行工具,实现一个命令完成热加载。

1.2.1 Spring Bean异步加载


Spring在启动过程中对于Bean的加载是顺序进行的,如果存在部分Bean加载耗时比较严重时,应用的启动时长会被严重拉长。Bean的加载耗时主要在init-method方法或@PostConstruct标识的方法,容器中的Bean多数不存在依赖关系,如果可以将Bean的初始化方法异步化,可以大大降低启动耗时。

Spring在启动过程中对于Bean的加载是顺序进行的,如果存在部分Bean加载耗时比较严重时,应用的启动时长会被严重拉长。Bean的加载耗时主要在init-method方法或@PostConstruct标识的方法,容器中的Bean多数不存在依赖关系,如果可以将Bean的初始化方法异步化,可以大大降低启动耗时。

主要依赖Spring提供一个BeanPostProcessor扩展点实现。BeanPostProcessor允许我们自定义bean的实例化和初始化过程。它是一个接口,定义了两个方法:

主要依赖Spring提供一个BeanPostProcessor扩展点实现。BeanPostProcessor允许我们自定义bean的实例化和初始化过程。它是一个接口,定义了两个方法:

postProcessBeforeInitialization(Object bean, String beanName):在bean初始化之前调用该方法,可以在初始化之前对bean对象进行任何自定义的修改或增强。

postProcessAfterInitialization(Object bean, String beanName):在bean初始化之后调用该方法。可以在bean初始化后对其进行任何自定义的修改或增强。

流程如下:

  1. 实现BeanPostProcessor扩展点

    • 在postProcessBeforeInitialization中判断beanName是否是配置异步初始化Bean
    • 如果需要异步化,查找init-method或者@PostConstruct修饰的方法
    • 动态代理初始化方法,将初始化方法扔到线程池中执行,并返回Future
  2. 实现ApplicationListener

    • 监听ContextRefreshedEvent事件,等待所有异步执行的init-method完成;
  3. 异步化的Bean可能在Spring Bean初始化顺序的末尾,导致异步优化效果不佳,支持优先加载配置异步化的Bean

    • InstantiationAwareBeanPostProcessorAdapter可以做到在Bean实例化之前,预先回调。优先加载异步初始化的Bean。

1.2.2 热加载


热加载的思路来自一个issue,通过这个issue接触到了trava-jdk-8-dcevm,其基于 DCEVM 并集成了 HotswapAgent ,与标准 JDK 不同(只支持方法体内代码修改的热加载),其允许更高级的热部署,如方法、字段添加等等,如果在日常/预发环境使用trava-jdk的热加载能力,日常开发效率可以有很大的提升。

但是因为日常开发中部署分支和开发分支往往不是同一个分支,要想使用此能力,需要一些操作步骤有点繁琐,所以便实现了一个命令行工具,支持一个命令实现代码热加载。原理如下:

image.png

效果如下:

image.png

2. 如何使用


2.1 分析能力

2.1.1 安装jar包


提供了手动安装和一键脚本安装两种安装方式

  1. 手动安装
  • 点击realease下载最新版tar.gz包
  • 新建文件夹,并解压
  1. 脚本安装(linux/mac)
curl -sS https://raw.githubusercontent.com/linyimin0812/spring-startup-analyzer/main/bin/install.sh | sh

脚本默认安装路径:$HOME/spring-startup-analyzer

2.1.2 配置项


本项目提供了以下几个配置项,不是必需配置项,可以直接使用默认配置。两种方式进行配置:

  1. 直接在配置文件中配置: 安装路径/spring-startup-analyzer/config/spring-startup-analyzer.properties

  2. 在启动参数中配置,如应用启动健康检查超时时间为30分钟:-Dspring-startup-analyzer.app.health.check.timeout=30

需要注意的是,判断应用启动成功的逻辑是:

  1. SpringApplication.run方法进行字节码增强,方法退出时则认为应用启动完成(仅对springboot应用生效)

  2. 轮询请求健康检查的url,返回200则认为启动完成(适用于所有spring应用)

  3. 以上两种方式均未成功时,超出应用启动健康检查超时时间则认为应用启动完成

如果是非springboot应用,需要通过spring-startup-analyzer.app.health.check.endpoints配置一下健康检查URL。

更多配置项

2.1.3


此项目是以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/spring-boot-demo.jar
  • IDEA中启动,则需要在VM options选项中添加

日志文件路径:安装路径/spring-startup-analyzer/logs

  • startup.log: 启动过程中的日志
  • transform.log: 被re-transform的类/方法信息

应用启动完成后会在console和startup.log文件中输出======= spring-startup-analyzer finished, click [http://localhost](http://localhost/):xxxx to visit details. ======,可以通过此输出来判断采集是否完成。

2.2 启动优化

2.2.1 Spring Bean异步加载


  1. 添加pom依赖
<dependency>
    <groupId>io.github.linyimin0812</groupId>
    <artifactId>spring-async-bean-starter</artifactId>
    <version>${latest_version}</version>
</dependency>
  1. 配置异步加载信息
# 异步化的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

2.2.2 热加载


  1. 在release下载spring-startup-cli

  2. 在项目的工作目录(HOME)下执行此命令行工具

java -jar spring-startup-cli.jar
  1. 使用config命令配置相关信息
config set
  1. 编码完成后执行reload命令,即可完成热加载

作者:linyimin
链接:https://juejin.cn/post/7294260754915573769
来源:稀土掘金

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1141843.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Netty进阶-黏包半包

黏包半包 1. 粘包与半包1.1 粘包现象1.3 现象分析1.4 解决方案方法1&#xff0c;短链接方法2&#xff0c;固定长度方法3&#xff0c;固定分隔符方法4&#xff0c;预设长度LengthFieldBasedFrameDecoder 1. 粘包与半包 1.1 粘包现象 服务端代码 Slf4j public class HelloWorl…

智能矩阵,引领商业新纪元!拓世方案:打破线上线下界限,开启无限营销可能!

在科技赋能商业大潮中&#xff0c;一切行业都在经历巨大变革&#xff0c;传统的营销策略被彻底改变&#xff0c;催生着无数企业去打造横跨线上线下、多维度、全方位的矩阵营销帝国。无数的成功案例已经告诉我们&#xff0c;营销不再只是宣传&#xff0c;而是建立品牌与消费者之…

JAVA实现校园失物招领管理系统 开源

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 招领管理模块2.2 寻物管理模块2.3 系统公告模块2.4 感谢留言模块 三、界面展示3.1 登录注册3.2 招领模块3.3 寻物模块3.4 公告模块3.5 感谢留言模块3.6 系统基础模块 四、免责说明 一、摘要 1.1 项目介绍 基于VueSpri…

甲骨文真的要开放Java EE?

甲骨文表示&#xff0c;目前正在与可能的几个候选基金会&#xff0c;以及许可证持有者和社区在进行谈判。随着Java EE 8平台的确定&#xff0c;甲骨文在周四表示&#xff0c;目前正在考虑将Java Enterprise Edition技术转移到开源社区。 甲骨文在其博客中说道&#xff0c;这次的…

数据结构介绍与时间、空间复杂度

数据结构介绍 什么是数据结构&#xff1f;什么是算法&#xff1f;数据结构和算法的重要性 数据结构定义 数据结构是计算机科学中研究数据组织、存储和管理的一门学科。数据结构描述了数据对象之间的关系&#xff0c;以及对数据对象进行操作的方法和规则。 常见的数据结构 数…

解决node项目一个极度困难的捕获异常却无法读取异常信息的问题

这个项目是集成了第三方NeteaseCloudMusicApi项目的接口代码&#xff0c;我没有直接使用它的接口&#xff0c;因为需要再跑一个npm run开个端口&#xff0c;感觉很麻烦。 所以下定决心&#xff0c;使用拆分代码的方式&#xff0c;硬生生将这个api项目的部分api接口代码集成到了…

JavaScript变量和作用域简介

目录 变量 var let const 作用域 全局作用域 局部作用域 总结 JavaScript是一种广泛应用于网页开发的脚本语言。在JavaScript中&#xff0c;变量和作用域是非常重要的概念&#xff0c;它们决定了代码中数据的存储和访问方式。本文将介绍JavaScript中的变量和作用域&…

如何使用Abaqus进行摩擦生热仿真

Abaqus除了可以对结构进行强度分析&#xff0c;同样也有强大的固体传热分析功能&#xff0c;下面通过一个简单的实例演示Abaqus的双向热固耦合分析。 因为本案例涉及物体表面辐射&#xff0c;因此需要定义绝对零度和输入史蒂夫-波兹曼常数&#xff0c;如下&#xff1a; 本次分…

ESP8266,手机与电脑之间的TCP通讯

电脑端运行通讯猫调试助手,作为服务端: 电脑端 电脑的IP地址是: 192.168.2.232 手机与电脑之间的TCP通讯 手机端运行网络调试精灵,作为客户端: 手机端 如果从手机端点击"发送"按钮,则也会将"ghhh东方红广场"几个字发送到电脑上(服务端). ESP8266作为客户…

接口自动化测试框架搭建完整版

1、基本目录的搭建 report&#xff1a;静态输出目录(报告或者日志) data&#xff1a;静态输入目录(可以存放Excel数据&#xff0c;被读取的一些数据) utils&#xff1a;实用方法层(这里存放的是项目的公共方法&#xff0c;一般拿到别的项目可以直接使用&#xff0c;列如&…

【列存储学习总结】

在 OpenGauss 中&#xff0c;列存储是一种高效的数据存储方式&#xff0c;它在处理分析查询和数据仓库工作负载时具有很高的性能优势。列存储将表中的数据按列存储在磁盘上&#xff0c;而不是按行存储&#xff0c;这样可以极大地提高数据读取和分析操作的效率。当涉及大量数据的…

护眼灯买哪种好? 推荐五款儿童护眼台灯

台灯如何选择&#xff0c;随着人们生活水平的提高及科技的不断进步&#xff0c;台灯的品质也得到了极大的提高&#xff0c;在生活中很多时候都需要使用台灯&#xff0c;但是市面上的台灯那么多&#xff0c;台灯如何选择。本次小编为大家推荐五款好用的护眼灯。 1.书客护眼台灯L…

一款功能强大的视频编辑软件会声会影2024中文破解版安装教程教程含会声会影2024注册机下载

会声会影2023中文破解版是一款功能强大的视频编辑软件、大型视频制作软件、专业视频剪辑软件。会声会影专业视频编辑处理软件&#xff0c;可以用于剪辑合并视频&#xff0c;制作视频&#xff0c;屏幕录制&#xff0c;光盘制作&#xff0c;视频后期编辑、添加特效、字幕和配音等…

关于亚马逊 CodeWhisperer 的使用体验

Amazon CodeWhisperer 是亚⻢逊出品的一款基于机器学习的 AI 编程助手&#xff0c;可实时提供代码建议。现在已正式可用&#xff0c;面向个人提供免费服务&#xff0c;通过在各种流行的IDE里集成 CodeWhisperer&#xff08;包括我们常用的 JetBrains 产品包及 Vscode 工具集&am…

Java实现快递管理系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 数据中心模块2.2 快递类型模块2.3 快递区域模块2.4 快递货架模块2.5 快递档案模块 三、界面展示3.1 登录注册3.2 快递类型3.3 快递区域3.4 快递货架3.5 快递档案3.6 系统基础模块 四、免责说明 一、摘要 1.1 项目介绍 …

node 第十三天 express初见

express概念 Fast, unopinionated, minimalist web framework for Node.js 快速、独立、极简的 Node.js Web 框架。 express相当于前端的jquery, 在不更改不侵入原生node的基础上封装了大量易用且实用的服务端api, express框架的封装原理就是前面第十天我们自己封装的简易服务器…

BI是什么?想要了解BI需要从哪些方面入手?

企业为了执行数字化战略&#xff0c;实行数字化转型&#xff0c;实现数据价值&#xff0c;除了需要相关数字化技术及理念、人才等&#xff0c;还需要借助数字化相关应用&#xff0c;例如商业世界中广受企业欢迎的ERP、OA、CRM等业务信息系统&#xff0c;以及上升势头非常迅猛的…

设计模式(2)-创建型模式

1&#xff0c;创建型模式 4.1 单例设计模式 单例模式&#xff08;Singleton Pattern&#xff09;是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类&#xff0c;该类负责创建自己…

c语言中各类指针的总结

1、数组指针 在c语言中&#xff0c;指针常被用于应用数组&#xff0c;或者作为数组的元素。顾名思义&#xff0c;指向数组的指针常被简称为数组指针。值得注意的是&#xff0c;数组指针指向的数组是数组名&#xff0c;也是其数值中首元素的地址。 我们定义数组指针的方式如下…

26 行为型模式-命令模式

1 命令模式介绍 2 命令模式原理 3 命令模式实现 模拟酒店后厨的出餐流程,来对命令模式进行一个演示,命令模式角色的角色与案例中角色的对应关系如下: 服务员: 即调用者角色,由她来发起命令. 厨师: 接收者,真正执行命令的对象. 订单: 命令中包含订单 /*** 订单类**/ public cl…