问题背景:最近,我负责一个订餐系统的业务研发,这个任务一开始并不难。然而,服务启动时间极其缓慢,慢得令人难以忍受。每次启动大约需要10 分钟,本质上是一次迭代和开发,大部分时间都花在项目启动上。我再也无法接受,所以我终于决定找出导致慢速启动的原因。
当我们开始寻找解决方案时,我们不知道如何优化项目的启动速度。我愚蠢地在百度上寻找解决方案。我立即寻找Jprofiler,一个可以快速找到错误堆栈位置的软件。不过,不得不说这个软件非常难用。不仅价格昂贵(MAC破解非常难找,即使找到了也打不开),而且很多Spring类实际上导致,Jprofiler根本无法定位错误。我尝试了Jprofiler,但不行,于是我在网上找到了另一种方法。您可以拍摄正在运行的线程的快照来检查是否有任何线程具有无限循环。这优化了启动速度。
如果你知道共同原因,线程转储会更好,但如果你不知道,盲目拦截线程实际上并不能帮助你识别当前线程是否有故障,这会很困难。虽然错误堆栈很全面,但这确实意味着您需要对源代码有更深入的了解。对于我这样的初学者来说,还是很难理解具体原因。
我用网上的解决方案彻底研究了无果,所以我决定用最笨的方法来解决:稍微调试一下。于是我在SpringBoot的启动类org.springframework.boot.SpringApplication#run中嵌入了调试点,将各个主要调试点一一进行了调试。
这种解决方案繁琐且耗时,但启动时间大约需要10分钟。然而,启动缓慢的原因很快就被查明了。 Springboot的BEAN后处理器加载方式有一个重要的bean容器DSLContext启动速度非常慢,大约需要6-7分钟。 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
但是dslContext 是什么以及为什么它会减慢我的系统启动速度?
文章中指出,dslContext启动缓慢的主要原因是AnnotationAwareAspectJAutoProxyCreator处理器,它会扫描dslContext中的方法,判断当前方法是否需要动态代理,我会一一判断。 dslContext 有大约800 多个方法,并且启动速度非常慢,这是可以理解的。
毕竟,一旦知道原因,就可以找到解决方案。只要Springboot不扫描这个dslContext组件,启动速度就会更快吧? 1.更改Springboot的扫描范围,以免扫描,2。不要导入DSLContext依赖项软件包,以便Springboot无法扫描它们,我首先尝试了第一个方法并更改了启动类。但是,无论我如何更改两个注释的扫描范围@componentscan和@enableFeignclients,它都没有真正的效果。 (最有可能的是,dslcontext没有用@component注释,并注入@configuration。)在绝望的情况下,唯一的选择是根据第二个想法考虑解决方案。您不能。然而,作为一个对天气敏感的项目,Maven 具有如此多的依赖项,以至于很难知道从哪里开始。我尝试通过Maven Helper插件搜索DSLContext的Maven依赖项,但无效。 (P.S.我必须在此处提及Maven Helper插件。此插件可以快速找到Maven依赖项,我通常用来排除相关依赖关系。这是您将使用的工具。)
于是,当我费尽心思在百度上搜索“use dslContext”这个关键词时,幸运的是,第二个搜索位置出现了jooq这个词。
所以我想知道,这个jooq依赖项是否导入了dslContext?我尝试搜索,但仍然如此!
我毫不犹豫地单击“排除”并重新开始。问题解决了!
经验总结:解决项目启动慢的原因,其实是一个非常依赖个人经验、运气、玄学的过程,但还是有一些方法可循的。 1.您可以想到Jprofiler录制线程启动时间。 (不过这次的效果不太好,可能需要更正常的打开。) 2、可以考虑通过快照的方式来查找线程。 3.最愚蠢的做法是使用Debug方法来确定位置。确定启动慢的具体原因后,如果是由于注入问题,有两种解决方案。 1.不扫描相应的组件组件可以通过更改@component和@enablefeignclients的basepackge参数来控制。 2.如果上述参数未生效,则可以考虑识别在BAIDU中引入此组件的Maven依赖关系,并使用Maven Helper插件排除依赖项。