系统启动太慢,调优后我直呼Nice

news2024/11/25 0:38:47


问题背景

最近在负责一个订单系统的业务研发,本来不是件困难的事。但是服务的启动时间很慢,慢的令人发指。单次启动的时间约在10多分钟左右,基本一次迭代、开发,大部分的时间都花在了启动项目上。忍无可忍的我,终于决定找到启动慢的原因。


方案探索

起初对于优化项目启动速度,是毫无头绪。也是傻傻的从百度上去搜解决的方案。一下子就搜到了Jprofiler这个软件,据说是能快速找到错误栈的位置。但是不得不说这软件真的很坑,不仅收费(MAC破解巨难找,找到了还打不开),而且实际因为很多Spring类都是采用动态代理加载的,Jprofiler根本判断不出来错误位置在哪。

尝试Jprofiler无果后,从网上还看到了一个另外的方法,可以通过对运行中的线程作快照,来定位是否存在有死循环的线程。进而优化启动速度。

5c74bea70ff12b2e65f6eb11ecc47fcb.jpeg

采用Thread dump的方式,比较适合你清楚大致原因的时候使用,否则你盲目的去截取到的线程,实际上也很难定位是不是当前线程的问题。尽管错误栈很全,但意味着你需要了解的源码更深。对我这种小白,依旧很难get到具体的原因。


深入钻研

采用网上的解决方案都无疾而终后,决定还是采用最笨的方法解决,就一点点的debug吧!于是在SpringBoot的启动类org.springframework.boot.SpringApplication#run上打满了debug点,逐个关键的debug点去调试。

d05c513be30848351724f199fcd3a884.jpeg

尽管方案很笨也很耗时,启动一次基本10分钟左右。但是很快定位到了启动缓慢的原因。在Springboot的BEAN后处理器的加载方法中,有一个关键的Bean容器DSLContext启动及其的慢,大概需要6、7分钟左右。org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

767bd69ba3d47b76ebf012bf471b0ab4.jpeg

然而,dslContext是个啥玩意,他为啥又让我的系统启动慢了呢?带着疑惑又搜了一遍百度,直到看到了这篇文章。https://www.jianshu.com/p/f65653a0f11c 。

fe527becbfc8320be59f27b03774c273.jpeg

文章里写到,dslContext启动慢的原因主要是有个:AnnotationAwareAspectJAutoProxyCreator的处理器,该处理器会扫描dslContext中的方法,并逐一判断当前的方式是否需要动态代理。dslContext中包含约800+的方法启动自然会很慢。

最终解决

知道了原因,那么自然也就知道了解决方案。只要让Springboot不扫描到这个dslContext组件了,那么就可以加快启动速度了不是?那么自然就可以从两个角度出发:

1、修改Springboot的扫描范围,不扫描即可;

2、不导入dslContext的依赖包,让Springboot扫描不到

我首先尝试了第一种方法,修改了启动类上@ComponentScan@EnableFeignClients的两个注解的扫描范围,然而,无论我怎么修改,实际上都没有生效。(大概率猜测是因为dslContext并不是采用@Componet注解的方式而是采用@Configuration注入的方式导致。)

无奈之下,只能按照第二种思路去考虑解决方案。然而,作为一个饱经风霜的项目,maven依赖多到数不清,根本不知道该从何下手。

尝试通过Maven Helper插件去搜索dslContext的maven依赖,却也是毫无作用。

(PS:这里不得不提一下Maven Helper这个插件,这个插件可以很快找到我们所依赖的maven,是我平日用来排除相关依赖的利器。)

54052704ed780221d59200d1023bd4de.jpeg

2902e62b9af2734358b670fef4321543.jpeg

也就是抱着尝试的心态,在百度下搜索了一下“使用dslContext”的关键字,很幸运的是,在第二个搜索位置跳出了jooq这个名词。

64a354dc10ff527471d6052b78004ba1.jpeg

于是怀疑,是不是这个jooq依赖把dslContext导入进来了呢?尝试着一搜,果然!

b123495580c6470d6df026df4eab3727.jpeg

毫不犹豫点击了exclude,再启动一次。问题解决!


经验总结

解决项目启动慢的原因其实是个很依靠个人经验和运气、玄学的过程,但是还是有一些方法有迹可循。

1、可以考虑Jprofiler去记录线程的启动时间。(但本次效果不佳,可能需要更正常的打开方式)

2、可以考虑采用截取线程快照的方式定位。

3、最最笨的方法就是采用Debug的方式定位。

在定位到具体的启动缓慢的原因后,如果是因为注入的问题,有下面两条解决思路:

1、不扫描对应的Component组件,可以通过修改@Component、@EnableFeignClients的basePackge参数来控制。

2、如果上述的参数没有生效,可以考虑尝试百度定位引入这个组件的maven依赖是什么,并借助Maven Helper插件将该依赖排除


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

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

相关文章

链路追踪——【Brave】第一遍小结

前言 微服务链路追踪系列博客,后续可能会涉及到Brave、Zipkin、Sleuth内容的梳理。 Brave 何为Brave? github地址:https://github.com/openzipkin/brave Brave是一个分布式追踪埋点库。 #mermaid-svg-riwF9nbu1AldDJ7P {font-family:"…

大数据Hadoop教程-学习笔记05【Apache Hive DML语句与函数使用】

视频教程:哔哩哔哩网站:黑马大数据Hadoop入门视频教程 总时长:14:22:04教程资源: https://pan.baidu.com/s/1WYgyI3KgbzKzFD639lA-_g 提取码: 6666【P001-P017】大数据Hadoop教程-学习笔记01【大数据导论与Linux基础】【17p】【P018-P037】大…

一文带你搞定线程池原理

1.使用线程池的意义何在?项目开发中,为了统一管理线程,并有效精准地进行排错,我们经常要求项目人员统一使用线程池去创建线程。因为我们是在受不了有些人动不动就去创建一个线程,使用的多了以后,一旦报错就…

Android从屏幕刷新到View的绘制(一)之 Window、WindowManager和WindowManagerService之间的关系

0. 相关分享 Android从屏幕刷新到View的绘制(一)之 Window、WindowManager和WindowManagerService之间的关系 Android从屏幕刷新到View的绘制(二)之Choreographer、Vsync与屏幕刷新 1. 相关类 WindowManagerService&#xff0c…

Linux安装Redis步骤

1 下载安装包并解压 官网:https://download.redis.io 下载安装包: wget https://download.redis.io/redis-stable.tar.gz 解压 tar -zxvf redis-stable.tar.gz* 2 安装 安装 cd redis-stable make install PREFIX/opt/install/redis6 设置环境变量 vi …

Python学习-----项目设计1.0(设计思维和ATM环境搭建)

目录 前言: 项目开发流程 MVC设计模式 什么是MVC设计模式? ATM项目要求 ATM项目的环境搭建 前言: 我个人学习Python大概也有一个月了,在这一个月中我发布了许多关于Python的文章,建立了一个Python学习起步的专栏…

企业级信息系统开发学习1.3——利用注解配置取代Spring配置文件

文章目录一、利用注解配置类取代Spring配置文件(一)打开项目(二)创建新包(三)拷贝类与接口(四)创建注解配置类(五)创建测试类(六)运行…

史上最经典垃圾回收器(CMS,G1)详解、适用场景及特点、使用命令

文章目录垃圾收集器介绍总结各个垃圾收集器之间的关系垃圾收集器使用命令及默认值详解各个垃圾收集器SerialParNewParallel ScavengeSerial OldParallel OldCMS(Concurrent Mark Sweep)G1(Garbage First)适用场景及推荐垃圾收集器介绍总结 垃圾收集器可以帮助我们进行具体的垃…

HDFS优化

单节点多块磁盘数据均衡 生成HDFS块均衡计划 hdfs diskbalancer -plan node1 执行均衡计划,node1.plan.json均衡计划文件 hdfs diskbalancer -execute node1.plan.json 查看当前均衡任务的执行情况 hdfs diskbalancer -query node1 取消均衡任务hdfs diskbalancer -cancel nod…

(三十九)undo log版本链是个什么东西?

今天我们正式开始切入讲解MySQL中多个事务并发执行时的隔离到底是怎么做的,因为我们知道默认是骚气的RR隔离级别,也就是说脏写、脏读、不可重复读、幻读,都不会发生,每个事务执行的时候,跟别的事务压根儿就没关系&…

移动web基础

初始缩小&#xff1a;布局视口大于视觉视口 初始放大&#xff1a;布局视口小于视觉视口 布局视口等于视觉视口&#xff08;这种动作行为叫做理想视口&#xff09; <meta name"viewport" content"width375" /> <meta name"viewport"…

云原生|kubernetes|网络插件flannel二进制部署和calico的yaml清单部署总结版

前言&#xff1a; 前面写了一些关于calico的文章&#xff0c;但感觉好像是浅尝辄止&#xff0c;分散在了几篇文章内&#xff0c;并且很多地方还是没有说的太清楚云原生|kubernetes|kubernetes的网络插件calico和flannel安装以及切换_calico换flannel_晚风_END的博客-CSDN博客 …

在C#中使用信号量解决多线程访问共享资源的冲突问题

目前在我写的233篇原创文章中&#xff0c;有两篇是粉丝可见的&#xff0c;其中《C#线程的参数传递、获取线程返回值以及处理多线程冲突》这篇文章有179个粉丝关注&#xff0c;看到不断有人关注这篇文章&#xff0c;这表明学习C#的人还是挺多的&#xff0c;感觉文章内容不够厚实…

泛型<E>

泛型 案例引出泛型 按要求写出代码&#xff1a; 在ArrayList中添加3个Dog对象&#xff0c;Dog对象有name和age两个属性&#xff0c;且输出name和age public class test1 {public static void main(String[] args) {ArrayList list new ArrayList();list.add(new Dog(10,&quo…

Python解题 - CSDN周赛第32期 - 运输石油(三维背包)

上期周赛因为最后一题出现bug&#xff0c;再加上都是经典的模板题&#xff0c;问哥就懒得写题解了。 本期也是有两道考过的题目&#xff0c;不过最后一题因为考到了背包问题的特殊类型&#xff0c;还是值得拿出来记个笔记。 第一题&#xff1a;传奇霸业 传奇霸业&#xff0c;是…

Unity高程图生成

序大概就是根据一个灰度图&#xff0c;生成一个地形。分两步来实现吧&#xff1b;首先&#xff0c;用随机数生成地形&#xff1b;然后&#xff0c;根据灰度图生成地形。小白&#xff0c;没啥基础&#xff0c;所以只能慢慢来。参考&#xff1a;【萌新图形学】地形网格生成入门 含…

基于stm32电梯管理系统设计

基于stm32电梯管理系统设计这里记录一下以前自己做的嵌入式课程设计&#xff0c;报告中的图片和文字太多了&#xff0c;全部一个一个把搬过来太麻烦了,需要完整文本和代码自行q我963160156&#xff0c;也可在微信公众号 *高级嵌入式软件* 里回复 *电梯* 查看完整版文章摘要关键…

Oracle Apex 21.2 安装过程

什么是 Oracle APEX&#xff1f; Oracle APEX 是广受欢迎的企业级低代码应用平台。借助该平台&#xff0c;您可以构建功能先进的可扩展安全企业应用&#xff0c;并在任何位置&#xff08;云或内部部署&#xff09;部署这些应用。 使用 APEX&#xff0c;开发人员可快速开发并部…

域组策略自动更新实验报告

域组策略自动更新实验报告 域组策略自动更新实验报告 作者: 高兴源 1要求、我公司为了完善员工的安全性和系统正常漏洞的维护&#xff0c;所以采用域组策略自动更新的方法来提高账户安全性&#xff0c;减少了用户的错误。 1.实验环境如下1台2008r2一台创建域&#xff0c;一台wi…

【云原生】k8s中Pod进阶资源限制与探针

一、Pod 进阶 1、资源限制 当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存大小&#xff0c;以及其他类型的资源。 当为 Pod 中的容器指定了 request 资源时&#xff0c;调度器就使用该信息来决定将 Pod 调度到哪个节点上。当还…