背景
專案之前一直使用Spring Cloud Dalston.SR5,但是此版本2018年12月軟體生命週期要結束,為了後續安全和維護的需要,需要將對版本進行升級。先從官網上分析D版本的後續版本的變更,發現大部分元件基本是相容的,這裡只列出對升級有重大影響的部分變化:
- Edgware:依賴的spring boot版本升級仍然是1.5, 許多元件的名稱變化
- Finchley:依賴的spring boot版本升級到2.0,真正的大版本升級,重大變化
- Greenwich:依賴的spring boot版本升級到2.1,支援java11
然後我們再搜尋網上其它人升級的經驗和難度,最後決定將目前的spring cloud直接升級最新版本:Greenwich.SR1
升級的詳細步驟和碰到的坑
spring-cloud-dependencies版本從Dalston.SR5到Greenwich.SR1
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
-->
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
複製程式碼
spring boot 版本從1.5.13 升級到2.1.4
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.13.RELEASE</version>
-->
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
複製程式碼
spring cloud的元件的artifactId名稱變更: 左邊是舊,右邊是新的
spring-cloud-starter-eureka --> spring-cloud-starter-netflix-eureka-client
spring-cloud-starter-eureka-server --> spring-cloud-starter-netflix-eureka-server
spring-cloud-starter-feign --> spring-cloud-starter-openfeign
spring-cloud-starter-hystrix -> spring-cloud-starter-netflix-hystrix
複製程式碼
將pom.xml中對應的artifactId名稱修改為最新的名稱 其它artifactId部分修改見這裡:E版本 github.com/spring-proj…
Feign的變化
feign除了上面提到元件的artifactId名稱重名為 spring-cloud-starter-openfeign外,還有以下部分發生變化:
包名發生改變:
org.springframework.cloud.netflix.feign.**.java -> org.springframework.cloud.openfeign.**.java
複製程式碼
@FeignClient增加一個屬性值contextId 之前的版本如果有存在兩個name屬性相同@FeignClient物件,不會報錯,但是升級後,會將相同name屬性的例項物件認為是同一個Bean從而丟擲如下異常: "The bean 'icc-authority.FeignClientSpecification', defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled."
解決方案是在@FeignClient註解裡增加contextId值將為bean id,如下:
@FeignClient(name="authority", fallbackFactory = IAccountServiceFallbackFactory.class, contextId = "accountService")
public interface IAccountService {
}
複製程式碼
Feign連線池 由於Spring Cloud D版本的Fegin使用httpclient做連線池,預設建立連線池物件的可配置項太少且連線池中可能存在處於半連線狀態的連線(關於httpclient半連線狀態bug見這篇文章 ),所以自己實現了HttpClient例項。到了G版本,如果實現Httpclient做連線池則,預設使用系統自己建立的httpclient物件,另外觀察原始碼HttpClientFeignLoadBalancedConfiguration 建立 httpclient的程式碼,不僅增加定時器關閉異常的連線解決半連線的問題,連線池的引數都是可配置的。
解決方案: 方案一. 所以去除自己的httpclient例項,使用預設的httpclient例項 方案二. 由於預設實現httpclient依然有部分引數不自由配置,我們仍然可以繼續使用自己的httpclient,在建立httpclient的方法上標記@Primay,且方法名稱不可以為httpclient,否則會報錯
@Bean
@Primary
public HttpClient httpClientDefault(FeignHttpClientPoolConfiguration feignHttpClientPoolConfiguration){
HttpClient httpClient = ….;
return httpClient;
}
複製程式碼
Spring Cloud Feign的檔案上傳實現的依賴jar包的升級 如果有使用feign實現檔案上傳,則會丟擲如下異常: Failed to parse multipart servlet request; nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found 解決方法: io.github.openfeign.form.feign-form和io.github.openfeign.form.feign-form-spring從3.0.3 版本升級到 3.8.0 commons-fileupload升級到1.4
無法找到jedis相關的元件
新版本使用Spring Data Redis 2.0,此版本已經將將jedis移除,預設使用的 Lettuce元件 解決方案一: 不使用jedis,直接升級到使用Lettuce,如果程式碼中沒有顯示使用jedis,建議使用此方案 然後對redis配置引數根據ide的提示修改即可 解決方案二: 增加jedis依賴
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
複製程式碼
Druid連線池版本升級
丟擲異常:Caused by: java.lang.ClassNotFoundException: org.apache.log4j 原因:新版本Spring Boot不要使用log4j,但是支援log4j2 解決方法: 1. 配置drui的屬性filters值為log4j2: 2. 升級com.alibaba.druid.jar包升級到1.1.16
分佈外掛pagehelper 升級:
異常:pagehelper 無法正常工作 原因:當前的使用pagehelper-spring-boot-starter 不支援spring boot 2.1.x 解決方案: 1. com.github.pagehelper: pagehelper-spring-boot-starter 升級到 1.2.10, 用於支援spring boot 2.1.x 2. 對應的 com.github.pagehelper: pagehelper 升級到5.1.8
屬性配置的變化:
應用的上下文路徑:server.context-path: authority --> server.servlet.context-path: authority 上傳檔案引數配置:spring.http.multipart.* -> spring.servlet.multipart.* 如原 spring.http.multipart.maxFileSize:5Mb -> spring.servlet.multipart.maxFileSize:5MB 同時這裡5Mb中的Mb的必須是大寫字母,必須是5MB,否則會丟擲異常:failed to convert java.lang.String to @org.springframework.boot.convert.DataSizeUnit org.springframework.util.unit.DataSize
@NotBlank, @NotEmpty 註解已經納入了JSR303,不需要在使用hibernate提供的註解了
org.hibernate.validator.constraints.NotBlank --> javax.validation.constraints.NotBlank org.hibernate.validator.constraints.NotEmpty --> javax.validation.constraints.NotEmpty
zipkin
在新的版本中,@EnableZipkinServer已經被標記@Deprecated,已經不推薦自行定製編譯服務的方式執行zipkin。官方推薦下載jar直接執行 curl -sSL zipkin.io/quickstart.… | bash -s java -jar zipkin.jar 詳細見這裡: github.com/apache/incu… github.com/apache/incu…
其它:
在升級後,經常丟擲沒有找到類的異常:java.lang.NoClassDefFoundError 對於這類錯誤,通過只要找到對應的jar將其升級到最新的版本就可以解決。 這也告訴我們如果要使用第三方的元件,一定要使用社群活躍的元件,否則一旦此元件出現安全問題或系統升級版本時,此元件不相容其它的元件,則必須要使用新元件替換此元件的功能。
版本升級後會有deprecated的類或方法,所以要注意看console中build的warning資訊 由於我們使用的Spring Cloud最近的版本,升級依賴jar通常只要升級到最新版本基本沒問題
Spring Cloud Netflix 進入專案進入維護模式階段
Spring Cloud Netflix 除了spring-cloud-netflix-eureka-* 和spring-cloud-netflix-concurrency-limits 模組以外,全部進入維護模式,詳細如下: ○ spring-cloud-netflix-archaius ○ spring-cloud-netflix-hystrix-contract ○ spring-cloud-netflix-hystrix-dashboard ○ spring-cloud-netflix-hystrix-stream ○ spring-cloud-netflix-hystrix ○ spring-cloud-netflix-ribbon ○ spring-cloud-netflix-turbine-stream ○ spring-cloud-netflix-turbine ○ spring-cloud-netflix-zuul
以下表中左邊的模組也已經進入維護模組,右邊是他的將來替代者
- Hystrix已經進入維護模式,建議使用Resillence4j替換,對應的Hystrix Dashboard和Turbine也會被淘汰,建議使用Resillence4j自帶Micrometer進行替換。 Resillence4j的孵化地址:github.com/spring-clou…
- Ribbion被Spring Cloud Loadbalancer替換,孵化地址:github.com/spring-clou…
- Zuu1 1 被 Spring Cloud GateWay替換: 有Spring Cloud Gateway和Zuul 1.x的效能對比:www.itmuch.com/spring-clou…
- Archaius 1的替代Spring Boot external config + Spring Cloud Config
什麼是維護模式:Spring Cloud 不會向對應的模組增加新的功能,但是他們仍然會修復出現的bug和安全問題,以及接受社群的pull request。 即使Greenwich版本被普遍採用後,Spring Cloud仍然保證會繼續支援以上的模組至少一年