记一次主干分支部署启动失败的排查。
起因
一天在电脑前安静的写代码,突然收到消息说「你上次发布是不是有问题,现在从 master 新拉的分支在预发部署不起来了」。
报错如下
Caused by: java.lang.IllegalStateException: Unable to load cache item at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:79) at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116) at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291) at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:480) at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:337) at org.springframework.context.annotation.ConfigurationClassEnhancer.createClass(ConfigurationClassEnhancer.java:138) at org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(ConfigurationClassEnhancer.java:110) at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:394) ... 20 more Caused by: java.lang.NoClassDefFoundError: com/alibaba/mcms/boot/service/interfaces/McmsResourceService at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) at java.lang.Class.getDeclaredMethods(Class.java:1975)
过程
round 1
McmsResourceService 属于 mcms-spring-boot-starter 这个包,作为一个有经验的的 Javaer,看到这个报错,第一反应是包冲突导致类找不到了。然而 checkout 到相应分支,看了下依赖关系,发现并没有依赖这个包,更别说多版本了。登线上机器验证,发现线上的 lib 目录下是有这个包的。好说,那应该是应用依赖了某个 snapshot 版本的二方包,然后从发布到现在该二方包有变更,导致依赖丢了。
然而这时候有同学发了这样一张图(现在看应该是他本地相关主 pom 没有更新,所以保留了这个依赖关系)。
round 2
看图可知这个二方包是这样被引入的,而且是通过正式包引入的。那么上面的猜想不成立了。
无妨,再针对这几个包对比下线上和预发的版本。发现线上的 common 是 1.1.1,而预发是 1.1.2 了。看了下 common 的 pom 文件,1.1.2 版本的确是显式地把 mcms-spring-boot-starter 给排掉了,而低版本还是在的。
再看下为什么 common 的版本号会变呢?common 是被 client 引入的,看下 client 的 pom 文件
... <parent> <groupId>com.wdk.backend</groupId> <artifactId>wdk-qualification-center</artifactId> <version>1.0.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.wdk.backend</groupId> <artifactId>wdk-qualification-center-client</artifactId> <version>1.1.1</version> <packaging>jar</packaging> <name>wdk-qualification-center-client</name> <dependencies> <dependency> <groupId>com.wdk.backend</groupId> <artifactId>wdk-qualification-center-common</artifactId> </dependency> ...
common 版本是定义在父 pom 里的,父 pom 是 SNAPSHOT 版本。看了下本地仓库的父 pom 的确在最近有升级,提升了 common 的版本。
至此,问题定位清楚了。
总结
- 大家发布正式二方包的时候,父 pom 也记得升一下吧
- 这次问题排查还是比较顺利的,因为那张图保留了现场。如果没有那张图,怎么定位?我想到的一个思路:mcms-spring-boot-starter 这个包被引入和被排除是确定的,只是不知道是在那个二方包的 pom 文件引入和排除的。那也好办,把 lib 下面的 jar 全部解压,然后用关键字搜索所有的 pom.xml 文件,应该能找到相应的线索。如果大家有更简单的思路欢迎留言