我服了!SpringBoot升級後這服務我一個星期都沒跑起來!(上)

2022-11-08 21:00:42

最近由於各方面的原因在準備升級 Spring Cloud 和 Spring Boot,經過一系列前置的調研和分析,決定把Spring Boot 相關版本從 2.1.6 升級到 2.7.5,Spring Cloud 相關版本從 Greenwich.SR1 升級為 2021.0.4。

升級包含基礎的業務服務程式碼的升級改造適配,還有就是中介軟體一堆程式碼的改造,上週經歷了一週的修改,用來測試的服務仍然還沒有跑起來,所以這篇文章我會記錄下來這升級過程中的一些問題,由於革命仍未成功,所以這是上篇。

1. hibernate-validator包下的類報錯

在 Spring Boot 2.3版本之後,spring-boot-starter-web 中沒有依賴 hibernate-validator。

解決方案:使用新的依賴。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2. ApplicationEnvironmentPreparedEvent類改變

Spring Boot 2.4版本之後,ApplicationEnvironmentPreparedEvent 建構函式新增了ConfigurableBootstrapContext,業務程式碼還好,應該都用不上這個類,中介軟體程式碼使用到的地方都需要修改。

解決方案:修改程式碼。

public ApplicationEnvironmentPreparedEvent(ConfigurableBootstrapContext bootstrapContext,
			SpringApplication application, String[] args, ConfigurableEnvironment environment) {
		super(application, args);
		this.bootstrapContext = bootstrapContext;
		this.environment = environment;
	}

3. junit依賴升級

升級後的junit版本預設是junit5(我沒有去確認是哪個版本發生了變化),升級之後包名發生了改變,所有的測試用例都需要修改。

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

另外發現Assert類不存在了,可以改用Assertions

Assertions.assertNotNull(result);

解決方案:修改程式碼!

4. Spring Cloud相容問題

由於測試過程中先升級的 Spring Boot,發現 Spring Cloud 使用到的低版本程式碼不相容,升級到文章開頭說的版本之後問題解決。

比如下面的 spring-cloud-context 啟動時候報錯。

5. SpringApplicationRunListener類改變

和第二個問題比較類似,SpringApplicationRunListener 中這兩個方法新增了 ConfigurableBootstrapContext,對應實現類都需要修改,這個應該無論在業務還是中介軟體程式碼中都應該有大量的使用。

解決方案:修改程式碼!

default void starting(ConfigurableBootstrapContext bootstrapContext) {}
default void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,ConfigurableEnvironment environment) {}

6. ServerProperties變更

spring-boot-autoconfigure 包下 ServerProperties 中的內部類 Tomcat 屬性變更,獲取最大執行緒數方法發生改變。

原寫法:serverProperties.getTomcat().getMaxThreads()

解決方案:serverProperties.getTomcat().getThreads().getMax()

7. spring-cloud-openfeign中移除ribbon和hystrix依賴

Commit地址:https://github.com/spring-cloud/spring-cloud-openfeign/commit/8a08e1ec4b4f0d40193a4ea9c03afdeffe3110a6

這個提交把 spring-cloud-openfeign 裡面關於 ribbon 和 hystrix 的依賴相關程式碼全部刪除了,這個 commit 我找了一遍 issue 和 PR,都沒有發現相關說明,大佬直接刪的,具體原因不清楚為什麼直接全刪乾淨了。

比如我的啟動報錯:

Caused by: java.lang.ClassNotFoundException: org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient

解決方案:手動引入新的依賴。

 <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
   <version>2.2.10.RELEASE</version>
 </dependency>

8. bootstrap.properties/yml 組態檔不生效

根據 Spring Cloud 設定方式,發現很多業務的本地設定設定在 bootstrap.properties中,新版本預設會不生效。

老版本中 spring.cloud.bootstrap.enabled 預設為 true。

新版本改過之後預設是false了,導致一堆設定不生效。

解決方案:手動設定spring.cloud.bootstrap.enabled=true

9. spring-cloud-netflix-eureka-client中移除ribbon和hystrix依賴

和第七個問題差不多,spring-cloud-netflix-eureka-client 移除了 ribbon和hystrix依賴,所以使用者端預設不會有ribbon這些東西了。

解決方案:手動引入新的依賴。

 <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
   <version>2.2.10.RELEASE</version>
 </dependency>

10. spring-cloud-starter-alibaba-sentinel版本不相容

spring-cloud-starter-alibaba-sentinel 使用的是 2.1.3.RELEASE ,和新版本存在相容性問題,導致無法啟動,存在迴圈依賴問題。

報錯資訊:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration': Unsatisfied dependency expressed through method 'setConfigurers' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.alibaba.cloud.sentinel.SentinelWebAutoConfiguration': Unsatisfied dependency expressed through field 'sentinelWebInterceptorOptional'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'com.alibaba.cloud.sentinel.SentinelWebAutoConfiguration': Requested bean is currently in creation: Is there an unresolvable circular reference?

解決方案:升級為當前 Spring Cloud 一樣的版本。

 <dependency>
   <groupId>com.alibaba.cloud</groupId>
   <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
   <version>2021.0.4.0</version>
 </dependency>

11. commons-pool2相容性報錯

spring-boot-autoconfigure 2.7.5版本中 JedisConnectionConfiguration 報錯,原因在於我們有的業務程式碼依賴中自己指定了 commons-pool2的版本。

Description:

An attempt was made to call a method that does not exist. The attempt was made from the following location:
    org.springframework.boot.autoconfigure.data.redis.JedisConnectionConfiguration.jedisPoolConfig(JedisConnectionConfiguration.java:114)

The following method did not exist:

    redis.clients.jedis.JedisPoolConfig.setMaxWait(Ljava/time/Duration;)V

Action:

Correct the classpath of your application so that it contains compatible versions of the classes org.springframework.boot.autoconfigure.data.redis.JedisConnectionConfiguration and redis.clients.jedis.JedisPoolConfig

Git Issue :https://github.com/spring-projects/spring-boot/issues/27642

看這個時間很早就修正了,commons-pool2 在2.8.1版本後丟失了一些方法。

解決方案:自己不要指定該包版本預設會使用 spring boot 的最新依賴,或者手動指定最新版本2.11.1。

12. 迴圈依賴報錯

spring-boot 2.6版本之後禁止迴圈依賴,有的話啟動會報錯,報錯資訊和第十個問題是一樣的,不同的是業務程式碼的報錯而已。

解決方案:手動解決程式碼迴圈依賴問題或者設定屬性 spring.main.allow-circular-references=true

13. spring-rabbit 版本相容

升級之後,由於中介軟體封裝了 rabbit 的一些功能,去掉了 spring-rabbit的自動裝配,導致基本上整個中介軟體包不可用,大量方法不相容。

解決方案:全部用2.7.5版本的程式碼覆蓋自動裝配的邏輯。

小總結

看起來這些問題都只是一兩句話的功夫,但是實際上花了大量的時間在排查、找解決方案,還有把所有現在依賴的包版本重新篩查,修改包版本、重新打包測試版本,中間非人體驗實在不是一兩句話能說清楚的,我覺得,做業務開發其實也挺好的。

目前革命還只是進行了一小步,還有更多的問題需要去解決,不過這個星期必須全部解決!!!