背景
项目之前一直使用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,否则会报错