Spring Boot启动慢如何分析

如果发现项目启动慢,你知道怎么分析慢的原因吗?

分析方法

自定义监听器

SpringApplicationRunListener是Spring Boot中的一个接口,它的作用是在SpringApplication运行的各个阶段提供回调接口,以便我们可以在这些阶段执行自定义的逻辑。SpringApplicationRunListener接口定义了以下几个方法:

  1. starting: 在SpringApplication运行开始时调用。

  2. environmentPrepared: 在Environment准备好,但在ApplicationContext创建之前调用。

  3. contextPrepared: 在ApplicationContext准备好,但在其加载源之前调用。

  4. contextLoaded: 在ApplicationContext加载源后调用。

  5. started: 在ApplicationContext刷新并启动后,但在SpringApplication.run方法完成之前调用。

  6. running: 在SpringApplication.run方法完成后调用。

  7. failed: 在SpringApplication运行失败时调用。

通过实现SpringApplicationRunListener接口,我们可以在SpringApplication运行的各个阶段执行自定义的逻辑,例如初始化资源、清理资源、记录日志等。下面的代码例子展示继承SpringApplicationRunListener接口并打印相应日志

@Slf4j
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
    // 这个构造函数不能少,否则反射生成实例会报错
    public MySpringApplicationRunListener(SpringApplication sa, String[] args) {
    }
    @Override
    public void starting() {
        log.info("starting {}", LocalDateTime.now());
    }
    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        log.info("environmentPrepared {}", LocalDateTime.now());
    }
    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        log.info("contextPrepared {}", LocalDateTime.now());
    }
    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        log.info("contextLoaded {}", LocalDateTime.now());
    }
    @Override
    public void started(ConfigurableApplicationContext context) {
        log.info("started {}", LocalDateTime.now());
    }
    @Override
    public void running(ConfigurableApplicationContext context) {
        log.info("running {}", LocalDateTime.now());
    }
    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        log.info("failed {}", LocalDateTime.now());
    }
}

对于每个Bean初始化耗时的监控,我们可以通过继承BeanPostProcessor接口方式,BeanPostProcessor 是Spring框架的一个接口,它定义了两个回调方法:postProcessBeforeInitialization和postProcessAfterInitialization。这两个方法分别在Bean初始化前后被调用。你可以在这两个方法中记录时间,然后计算出Bean初始化的耗时。

@Component
public class BeanInitiateTimeCost implements BeanPostProcessor {
    private Map<String, Long> costMap = Maps.newConcurrentMap();
  
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        costMap.put(beanName, System.currentTimeMillis());
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (costMap.containsKey(beanName)) {
            Long start = costMap.get(beanName);
            long cost  = System.currentTimeMillis() - start;
            if (cost > 0) {
                costMap.put(beanName, cost);
                System.out.println("bean: " + beanName + "\ttime: " + cost);
            }
        }
        return bean;
    }
}

通过Actuator实现

前提条件: Spring Boot启动跟踪需要Spring boot的版本在2.4及以上。相关步骤

  1. 添加相关依赖

引入spring-boot-starter-actuator

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2.暴露startup路径

将下面配置加入到application.properties, 从而暴露startup链接

management.endpoints.web.exposure.include=startup

  1. 使用BufferingApplicationStartup的方式启动程序

在使用Spring Actuator分析Spring Boot启动慢的问题时,你需要在程序启动时启用BufferingApplicationStartup。这是因为Spring Boot 2.4.0及以上版本的Actuator的/actuator/startup端点使用BufferingApplicationStartup来收集启动过程的信息。

public class Application {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Application.class);
        application.setApplicationStartup(new BufferingApplicationStartup(2048));
        application.run(args);
    }
}

在这个例子中,我们创建了一个BufferingApplicationStartup实例,并设置了缓冲区大小为2048。然后我们将这个BufferingApplicationStartup实例设置为SpringApplication的ApplicationStartup。

这样,当你启动应用程序并访问/actuator/startup端点时,你就可以看到启动过程的详细信息,包括每个bean的启动时间。你可以根据这些信息找出启动时间较长的bean,并进行优化。

返回结果分析

curl 'http://localhost:8080/actuator/startup' 返回JSON格式的数据,如下

{
    "springBootVersion": "2.6.3",
    "timeline": {
        "startTime": 1698287960.140000000,
        "events": [
            {
                "endTime": 1698287960.176000000,
                "duration": 0.018000000,
                "startupStep": {
                    "name": "spring.boot.application.starting",
                    "id": 0,
                    "tags": [
                        {
                            "key": "mainApplicationClass",
                            "value": "com.yuehuijiankang.blood.pressure.BloodPressureServiceApplication"
                        }
                    ],
                    "parentId": null
                },
                "startTime": 1698287960.158000000
            },
   ........         

startupStep中可以查看具体的执行步骤和耗时情况。借助jq工具可以方便分析JSON数据。比如,如果我们想查看Bean初始化最慢的前10个bean。我们可以执行下面命令:

curl 'http://localhost:8080/actuator/startup' -X POST | jq '[.timeline.events | sort_by(.duration) | reverse[] | select(.startupStep.name | match("spring.beans.instantiate")) | {beanName: .startupStep.tags[0].value, duration: .duration}] | .[:10]'

返回结果如下:

图片

总结

如果你发现Spring Boot项目启动慢,可以通过以下两种方法进行分析:

  1. 自定义监听器:通过实现SpringApplicationRunListener接口,可以在SpringApplication运行的各个阶段执行自定义的逻辑,例如记录每个阶段的时间。此外,可以通过实现BeanPostProcessor接口,记录Bean初始化前后的时间,从而计算出Bean初始化的耗时。

  2. 使用Actuator:Spring Boot 2.4及以上版本的Actuator提供了/actuator/startup端点,可以收集启动过程的信息。首先,需要在pom.xml文件中添加spring-boot-starter-actuator依赖,并在application.properties文件中暴露startup端点。然后,需要在程序启动时启用BufferingApplicationStartup。最后,通过访问/actuator/startup端点,可以看到启动过程的详细信息,包括每个bean的启动时间。

通过以上两种方法,可以找出启动时间较长的阶段或Bean,并进行相应的优化。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【期末复习向】长江后浪推前浪之ChatGPT概述

参考文章&#xff1a;GPT系列模型技术路径演进-CSDN博客 这篇文章讲了之前称霸NLP领域的预训练模型bert&#xff0c;它是基于预训练理念&#xff0c;采用完形填空和下一句预测任务2个预训练任务完成特征的提取。当时很多的特定领域的NLP任务&#xff08;如情感分类&#xff0c…

解决下载huggingface模型权重无法下载的问题

文章目录 方法一(推荐)方法二方法三依然存在的问题 由于某些原因&#xff0c;huggingface的访问速度奇慢无比&#xff0c;对于一些模型(比如大语言模型LLM)的权重文件动辄几十上百G&#xff0c;如果用默认下载方式&#xff0c;很可能中断&#xff0c;这里推荐几种方式。 方法一…

论文自己改过后怎么降重 papergpt

大家好&#xff0c;今天来聊聊论文自己改过后怎么降重&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff0c;可以借助此类工具&#xff1a; 论文自己改过后如何降重 在论文修改过程中&#xff0c;我们往往会对…

最新AI绘画Midjourney绘画提示词Prompt教程

一、Midjourney绘画工具 SparkAi【无需魔法使用】&#xff1a; sparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的…

VR云游打造沉浸式文旅新体验,延伸智慧文旅新业态

从“跃然纸上”到“映入眼帘”&#xff0c;随着国家数字化战略的深入实施&#xff0c;文旅产业的数字化转型正在不断加快&#xff0c;“沉浸式”逐渐成为了文旅消费新热点。VR技术与文旅产业相融合&#xff0c;新产品、新模式、新业态不断涌现&#xff0c;文旅资源逐渐“活”起…

ACT、NAT、NATPT和EASY-IP

目录 一、ACL 1.ACL 2.ACL的两种应用匹配机制 3.ACL的基本类型 4.ACL命令操作 5.ACL实验&#xff1a; 4.ACL的应用原则&#xff1a; 5.匹配原则&#xff1a; 二、NAT 1.NAT的原理及作用&#xff1a; 2.NAT分类 3.NAT配置 三、EASY-ip实验 四、NATPT 五、通配符 …

Nginx七层代理,四层代理 + Tomcat多实例部署

目录 1.tomcat多实例部署 准备两台虚拟机 进入pc1 pc2同时安装jdk 进入pc1 pc2安装tomcat PC1配置&#xff08;192.168.88.50&#xff09; 安装tomcat多实例 tomcat2中修改端口 启动tomcat1 tomcat2 分别在三个tomcat服务上部署jsp的动态页面 2.nginx的七层代理&…

使用opencv的Canny算子实现图像边缘检测

1 边缘检测介绍 图像边缘检测技术是图像处理和计算机视觉等领域最基本的问题&#xff0c;也是经典的技术难题之一。如何快速、精确地提取图像边缘信息&#xff0c;一直是国内外的研究热点&#xff0c;同时边缘的检测也是图像处理中的一个难题。早期的经典算法包括边缘算子方法…

使用set和emit在uni-app中实现响应式属性和自定义事件

在uni-app中&#xff0c;我们经常需要动态设置响应式属性&#xff0c;并且通过自定义事件来实现组件间的通信。这时&#xff0c;我们可以使用set和emit来轻松实现这些功能。 使用$set动态设置响应式属性 在Vue中&#xff0c;我们可以使用来动态设置响应式属性。在uniapp中使用…

java基础知识④:设计模式

目录 一、设计模式 1️⃣创建型设计模式&#xff08;常用&#xff1a;单例、工厂、抽象工厂&#xff09; 2️⃣结构型设计模式&#xff08;常用&#xff1a;适配器、装饰者、外观、代理&#xff09; 3️⃣行为型设计模式&#xff08;常用&#xff1a;观察者、策略、模板方法、命…

如何使用ArcGIS Pro裁剪影像

对影像进行裁剪是一项比较常规的操作&#xff0c;因为到手的影像可能是多种范围&#xff0c;需要根据自己需求进行裁剪&#xff0c;这里为大家介绍一下ArcGIS Pro中裁剪的方法&#xff0c;希望能对你有所帮助。 数据来源 本教程所使用的数据是从水经微图中下载的影像和行政区…

Springboot的火车票订票系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; Springboot的火车票订票系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#…

Spring Boot整合Sharding-JDBC实现数据脱敏

目录 背景ShardingSphere脱敏规则sharding-jdbc数据脱敏数据脱敏配置数据分片 数据脱敏配置 背景 对互联网公司、传统行业来说&#xff0c;数据安全一直是极为重视和敏感的话题。数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形&#xff0c;实现敏感隐私数据的可靠保护…

【Avue】点击新增再点击表单得radio选项出现新表单,且编辑页面关不掉新表单处理方法

一、问题描述 1、点击新增 2、 点击radio选择值 1、点击否得时候没反应 2、点击是得时候出现新表单 2.1、旧代码 {label: 是否危险源,prop: isBigdanger,searchLabelWidth: 120,overHidden: true,span: 24,rules: [{required: true,message: 请选择是否重大危险源,trigger: bl…

Mapreduce小试牛刀(2)--java api

1.同hdfs 的java api,我们首先要在IDE中建立一个maven项目 pom.xml中配置如下&#xff1a; <dependencies><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-mapreduce-client-common</artifactId><version>3.…

磁盘坏道扫描工具 Macrorit Disk Scanner v6.7.0 中文免费版 -供大家学习研究参考

非常方便实用的磁盘坏道修复软件。Wipe Bad Disk功能强大好用&#xff0c;通过特殊的算法来强制将硬盘的坏道删除清空格式化&#xff0c;从而拯救因产生坏道而不敢继续使用的硬盘!要注意的是经过这块软件清空的硬盘数据基本上是不能被恢复的&#xff0c;所以操作前请一定要备份…

武林风云之linux组软raid0

小y可喜欢玩文明系列的游戏了&#xff0c;因为小y也一直喜欢造轮子&#xff0c;属于自己的轮子。 每次小y听到”要向雄鹰一样&#xff0c;定要遨游于天际。”感觉自己给自己打了一针强心剂&#xff0c;要求自己拼搏进取。 众所周知&#xff0c;文明是个原生的linux游戏&#xf…

Linux 系统 yum 安装 jdk1.8

1、首先检查是否存在jdk java -version上图这样就是系统没有找到已经安装的jdk 2.查看jdk版本列表 yum -y list java*执行此命令会显示所有版本 jdk 安装包 3、下载安装jdk 这里安装的是jdk1.8 yum install java-1.8.0-openjdk-devel.x86_64这里输入回车y继续安装 4、再次检…

学习Django从零开始之三

搭建虚拟python环境 搭建开发环境有多种方式&#xff0c;其中包括本地直接安装Python的可执行文件&#xff0c;使用virtualenv&#xff0c;以及使用Anaconda和Miniconda等工具。这些工具在创建Python虚拟环境方面各有特点。具体不同之处感兴趣的同学可以自行查阅相关资料。 简…

docker consul 容器的自动发现与注册

consul相关知识 什么是注册与发现 服务注册与发现是微服务架构中不可或缺的重要组件。起初服务都是单节点的&#xff0c;不保障高可用性&#xff0c;也不考虑服务的压力承载&#xff0c;服务之间调用单纯的通过接口访问。直到后来出现了多个节点的分布式架构&#xff0c;起初的…