likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 14

问题背景

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

方案探索

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

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

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

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

深入钻研

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

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

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

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

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

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

文章里写到,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,是我平日用来排除相关依赖的利器。)

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

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

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

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

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

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

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

经验总结

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

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

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

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

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

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

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