项目中使用了springboot2.0.4,并集成了elasticsearch、dubbo等组件。在更新了创库代码后,发现突然程序启动不了,总是启动后tomcat自动关闭,日志信息如下:
很纳闷 :-(,任何异常日志都没有,出什么情况了?
第一感觉是程序有问题,更新了代码导致。可是本次更新的代码量有比较大,从源代码比对分析不靠谱,需要大量时间。另外源码有问题启动日志也应该要有报错信息。
是日志级别不对吗?
检查配置logging.level.root
已经是INFO
级别了,且没有其它级别控制。尝试将logging.level.root=debug
,重启发现依然没有任何异常信息展现。
日志输出组件冲突了吗?
由于笔者之前有过log4j
框架切换logback
的经验,因此怀疑pom
中引入的组件传递依赖了一些不需要的jar
包,导致日志组件冲突。
检查pom
文件发现:
elasticsearch-rest-client-sniffer
与dubbo
组件传递依赖引入了common-logging
组件。导致spring-jcl
组件的org.apache.commons.logging.LogFactory
没有被加载,而使用了common-logging
中的org.apache.commons.logging.LogFactory
类; 这是因为在JVM环境中存在同名的的class,类加载器根据加载顺序选择的。在
spring-jcl
的LogFactory
中,实现逻辑是如果log4j2
的jar
包存在,这优先使用log4j2
来记录日志、然后才是slf4j
。而在common-logging
的LogFactory
中,实现逻辑是如果log4j
的jar
包存在,优先采用log4j
、然后采用jdk的util包中的logger记录。在我们的启动环境中,我们采用通过
spring-boot-starter-logging
组件来输出日志,其默认采用的是slf4j-api
来通过logback
记录日志,log4j2
组件是不存在的,于是springboot
在启动时,因为类加载器的原因使用了common-logging
的LogFactory
,又因为dubbo
、zookeeper
、zkclient
引入了log4j
组件,导致springboot
启动时的部分日志输出到了log4j
,因此异常被吃掉了。
解决办法
在依赖的“elasticsearch-rest-client-sniffer”、“dubbo”组件中排除掉对common-logging
的依赖。
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client-sniffer</artifactId>
<version>${elasticsearch.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
解决后重启程序,终于看到了异常原因: