記一次主幹分支部署啟動失敗的排查。
起因
一天在電腦前安靜的寫代碼,突然收到消息說「你上次發佈是不是有問題,現在從 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 文件,應該能找到相應的線索。如果大家有更簡單的思路歡迎留言