開發與維運

依賴正式包,應用就穩了嗎

記一次主幹分支部署啟動失敗的排查。

 

起因

一天在電腦前安靜的寫代碼,突然收到消息說「你上次發佈是不是有問題,現在從 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 的版本。

image.png

 

至此,問題定位清楚了。

 

總結

  1. 大家發佈正式二方包的時候,父 pom 也記得升一下吧
  2. 這次問題排查還是比較順利的,因為那張圖保留了現場。如果沒有那張圖,怎麼定位?我想到的一個思路:mcms-spring-boot-starter 這個包被引入和被排除是確定的,只是不知道是在那個二方包的 pom 文件引入和排除的。那也好辦,把 lib 下面的 jar 全部解壓,然後用關鍵字搜索所有的 pom.xml 文件,應該能找到相應的線索。如果大家有更簡單的思路歡迎留言

Leave a Reply

Your email address will not be published. Required fields are marked *