最近由於各方面的原因在準備升級 Spring Cloud 和 Spring Boot,經過一系列前置的調研和分析,決定把Spring Boot 相關版本從 2.1.6 升級到 2.7.5,Spring Cloud 相關版本從 Greenwich.SR1 升級為 2021.0.4。
升級包含基礎的業務服務程式碼的升級改造適配,還有就是中介軟體一堆程式碼的改造,上週經歷了一週的修改,用來測試的服務仍然還沒有跑起來,所以這篇文章我會記錄下來這升級過程中的一些問題,由於革命仍未成功,所以這是上篇。
在 Spring Boot 2.3版本之後,spring-boot-starter-web
中沒有依賴 hibernate-validator。
解決方案:使用新的依賴。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
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;
}
升級後的junit版本預設是junit5
(我沒有去確認是哪個版本發生了變化),升級之後包名發生了改變,所有的測試用例都需要修改。
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
另外發現Assert
類不存在了,可以改用Assertions
。
Assertions.assertNotNull(result);
解決方案:修改程式碼!
由於測試過程中先升級的 Spring Boot,發現 Spring Cloud 使用到的低版本程式碼不相容,升級到文章開頭說的版本之後問題解決。
比如下面的 spring-cloud-context
啟動時候報錯。
和第二個問題比較類似,SpringApplicationRunListener
中這兩個方法新增了 ConfigurableBootstrapContext,對應實現類都需要修改,這個應該無論在業務還是中介軟體程式碼中都應該有大量的使用。
解決方案:修改程式碼!
default void starting(ConfigurableBootstrapContext bootstrapContext) {}
default void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,ConfigurableEnvironment environment) {}
spring-boot-autoconfigure
包下 ServerProperties 中的內部類 Tomcat 屬性變更,獲取最大執行緒數方法發生改變。
原寫法:serverProperties.getTomcat().getMaxThreads()
解決方案:serverProperties.getTomcat().getThreads().getMax()
這個提交把 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>
根據 Spring Cloud 設定方式,發現很多業務的本地設定設定在 bootstrap.properties
中,新版本預設會不生效。
老版本中 spring.cloud.bootstrap.enabled
預設為 true。
新版本改過之後預設是false了,導致一堆設定不生效。
解決方案:手動設定spring.cloud.bootstrap.enabled=true
和第七個問題差不多,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>
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>
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。
spring-boot
2.6版本之後禁止迴圈依賴,有的話啟動會報錯,報錯資訊和第十個問題是一樣的,不同的是業務程式碼的報錯而已。
解決方案:手動解決程式碼迴圈依賴問題或者設定屬性 spring.main.allow-circular-references=true
。
升級之後,由於中介軟體封裝了 rabbit 的一些功能,去掉了 spring-rabbit
的自動裝配,導致基本上整個中介軟體包不可用,大量方法不相容。
解決方案:全部用2.7.5版本的程式碼覆蓋自動裝配的邏輯。
看起來這些問題都只是一兩句話的功夫,但是實際上花了大量的時間在排查、找解決方案,還有把所有現在依賴的包版本重新篩查,修改包版本、重新打包測試版本,中間非人體驗實在不是一兩句話能說清楚的,我覺得,做業務開發其實也挺好的。
目前革命還只是進行了一小步,還有更多的問題需要去解決,不過這個星期必須全部解決!!!