Spring Boot 2.0.x 版本信息 Spring Boot 2.1.x 版本信息 Spring Boot 1.5.x ~ 2.0 迁移指南 Spring Boot 官方文档地址

截止至 2021-10当前 Spring Boot 最新版本已经到了 Spring Boot 2.6.x
Spring Boot 最新稳定版本,即 RELEASE 版本是 2.3.9.RELEASE

分布式架构中,Spring Cloud 基于 Spring Boot 提供一系列分布式组件,包括但不限于:注册中心、配置中心、链路追踪等。

Spring Boot 和 Spring Cloud 存在版本依赖,对应版本依赖如下表:

image.png
关于 Spring Cloud 版本,GreenwichFinchleyEdgwareDalston生命周期已经结束,不在支持。
不过相关的bug 以及功能兼容,会在对应的 RELEASE(RS) 版本后追加。

一、升级前准备工作

待升级系统版本:

  • Spring Boot 1.5.7
  • Spring Cloud edgware SR5 (更新时间:2018-10-16
    Spring Cloud Edgware 最新版本 SR6 也与 2019-05-23 结束生命周期

在进行升级前主要考虑到两个问题

  • 问题一:1.x 升级 2.x 的必要性
  • 问题二:升级版本的确定

    1.1、Spring Boot 1.x 升级 Spring Boot 2.x 的必要性

从开发角度看,软件的升级主要是围绕如下几点

  • 增加新特性
  • 提升性能
  • 修复相关bug

而从是否升级的角度来看,就需要关注几个点

  • 新版本已修复的漏洞对当前项目的必要性
  • 新特性给项目带来的帮助
  • 性能提升带来的效果
  • 是否有相关的技术能力,以及人员去做处理

// TODO Spring Boot 2.0 带来的新的版本特新,以及升级的必要性。

1.2、Spring Boot 及 Spring Cloud 版本选择

下图,是当前 Spring Boot 和 Spring Cloud 版本对应表
image.png

处于稳定考虑,2.3.x不进入考虑范围。虽然 Spring Boot 2.3.x 已经有多个稳定的RELEASE 版本。但是生产环境更多考虑的就是稳定性。

官方文档中,给到的建议是,先从 Spring Boot 1.5.x升级到 Spring Boot 2.0.x然后在逐步进行升级,相关文档说明:
image.png

鉴于项目系统中的部分项目在使用的 Spring Boot 2.1.5.RELEASE版本,有一定的使用经验。

同时翻阅 Spring Boot 2.0.x 升级 2.1.x 相关文档Spring Boot 2.1.x 升级 2.2.x相关文档,对比版本升级中可能涉及到的升级变更。

最终决定升级版本: Spring Boot 2.1.18.RELEASE 版本(2.1.x 最新稳定版本),对应的 Spring Cloud 版本 GreenwichSR6

虽然 Spring Cloud GreenwichSR62020-05-15后不在进行开发支持,不过作为一个最新稳定版本来说也算是合适的选择。

出于稳定考虑不选择 Spring Boot 2.xSpring Cloud Hoxton,因为版本升级跨度太大,可能出现的版本变更过多,不适合直接升级到该版本,等后期稳定后,可以针对系统一步一步进行升级改版,循序渐进。

1.3、当前系统微服务结构

image.png
版本升级可能涉及到的变更

  • Spring Boot Admin 升级变更
    关联对应的 spring-boot-actuator``Hystrix Dashboard
  • Ribbon/Open FeignAPI变更
  • 经测试基本 Spring Cloud ConfigSpring Cloud Eureka能够兼容旧版本 API,依情况后期升级变更。

    二、版本升级相关记录

    2.1、Spring Boot Admin(应用监控升级)

    Spring Boot Admin GItHub Spring Boot Admin 2.3.1 指南

2.1.1、SBA 升级必要性

Spring Boot 2.0.x Actuator 变更部分内容
Spring Boot 2.1.x Actuaotr 变更部分内容
Spring Boot 1.5.x ~ 2.0.x 迁移指南
(进入页面,全局搜索 Actuator 关键字即可)
Spring Boot Admin 部分变更信息如下

  • 除了 /health/info监控端点不在开放(2.0.x 版本)
  • 配置变更:endpoints..enabled 变更为 management.endpoint..enabled(2.0.x 版本)
  • endpoints.<id>.id 没有发生变更,(id 不在支持配置)(2.0.x 版本)
  • endpoints..path 变更为 management.endpoints.web.path-mapping.(2.0.x 版本)
  • /actuator/mappings/actuator/httptrace 进行全面改造(2.0.x 版本)
  • 自定义端点,需要进行重新改造(2.0.x 版本)
  • 新增端点 /actuator/integrationgraph 等,参考:API(2.1.x 版本)
  • /info and /health 不在对外暴露,需要配置暴露(2.1.x版本)

更多变更,翻阅相关文档。
Spring Boot Amdin 2.x 可以兼容 Spring Boot 1.5.x 的监控,但是 Spring Boot Admin 1.x 无法兼容 Spring Boot 2.x 的监控。

2.1.2、Spring Boot Admin(应用监控)

Spring Boot Admin 官方提供了三个版本的指南,分别是:

  • 1.5.7
  • 2.3.1
  • 2.4.3

当前项目使用的 1.5.7 进行应用监控,Spring Boot 升级,对应的 SBA server 对应的升级到2.x版本。
选取 2.1.6作为升级版本,不求最新,但求最稳。

升级需要关注的问题

  • 1、是否在线上关闭 HttpTrace
    在更新的版本中 Spring Boot Admin 默认不开启HttpTrace 功能。
    HttpTrace 默认在应用中占用了 1000个对象,用来缓存记录请求,可以使用其他监控工具替换。
  • 2、HttpTrace 页面崩溃问题(解决跳转
  • 3、Hystrix 面板默认不在支持(解决跳转)(聚合界面集成不在支持)
  • 4、自定义 Endpoint 写法变更(解决跳转
  • 5、[CounterService 废弃](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide#migrating-custom-countersgauges),需要是要使用 Metrics替换,参考案例:CounterService.java
  • 6、MetricRegistry不在自动配置,使用到的需要自行实例,或者使用 Metrics替换。
  • 7、旧版本配置信息废弃,如:参考官方文档,或者引入 spring-boot-properties-migrator依赖,协助废弃依赖排查。

2.2、Eureka(注册中心)

2.2.1、应用依赖 Eureka client

A、依赖变更
  1. <!-- eureka client New-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  5. </dependency>
  6. <!-- eurek clietn Old -->
  7. <dependency>
  8. <groupId>org.springframework.cloud</groupId>
  9. <artifactId>spring-cloud-starter-eureka</artifactId>
  10. </dependency>

B、启动报错问题(guava 版本问题)

image.png
Spring CLoud Eureka 2.1.5.RELEASE 对应的 guava 版本 缺少方法 ,通过替换新版本解决问题,引入的依赖如下

  1. <dependency>
  2. <groupId>com.google.guava</groupId>
  3. <artifactId>guava</artifactId>
  4. <version>23.0</version>
  5. </dependency>

2.2.2、Eureka Server 升级

低版本 Eureka 能够兼容新版本 Spring Boot 的注册,后期在进行统一更新。

2.3、Open Feign(组件)

A、依赖变更

  1. <!-- Open Feign New-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-openfeign</artifactId>
  5. </dependency>
  6. <!-- Open Feign Old -->
  7. <dependency>
  8. <groupId>org.springframework.cloud</groupId>
  9. <artifactId>spring-cloud-starter-feign</artifactId>
  10. </dependency>

B、引用路径变更

旧版:import org.springframework.cloud.netflix.feign.FeignClient
新版:import org.springframework.cloud.openfeign.FeignClient

旧版:import org.springframework.cloud.netflix.feign.EnableFeignClients
新版:import org.springframework.cloud.openfeign.EnableFeignClients

2.4、Hystrix(组件)

依赖变更

  1. <!-- Hystrix New-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  5. </dependency>
  6. <!-- Hystrix Old -->
  7. <dependency>
  8. <groupId>org.springframework.cloud</groupId>
  9. <artifactId>spring-cloud-starter-hystrix</artifactId>
  10. </dependency>

2.5、Mybatis(组件)

该步骤可以省略。 项目使用的原生 Mybatis ,使用 tk Mapper 替换,节省基础SQL编写时间。

mybatis 升级 tk mapper
版本信息 - 参考连接
image.png

2.6、Redis 依赖(组件)

A、依赖变更

项目中 Redis 的使用依赖组件:spring-boot-starter-data-redis,Spring Boot 1.5.x 默认使用的 Jedis Client,在Spring Boot 2.x 后,默认使用 io.lettuce:lettuce-core,且默认不提供池化技术。
方案两种

  • 替换Jedis为默认的 io.lettuce:lettuce-core
  • 使用 Jedis替换新版依赖

沿用 Jedis客户端的方式,减少代码升级代码编码量,相关引用依赖如下:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-redis</artifactId>
  4. <exclusions>
  5. <!-- 剔除 lettuce 依赖 -->
  6. <exclusion>
  7. <groupId>io.lettuce</groupId>
  8. <artifactId>lettuce-core</artifactId>
  9. </exclusion>
  10. </exclusions>
  11. </dependency>
  12. <!-- 连接池 -->
  13. <dependency>
  14. <groupId>org.apache.commons</groupId>
  15. <artifactId>commons-pool2</artifactId>
  16. </dependency>
  17. <!-- jedis 客户端依赖 -->
  18. <dependency>
  19. <groupId>redis.clients</groupId>
  20. <artifactId>jedis</artifactId>
  21. </dependency>

B、配置变更

部分配置已经变更,如:spring.redis.pool.max-active
具体通过官方文档,或者借助 spring-boot-properties-migrator 完成配置替换,替换后,部分配置如下

  1. ## redis config
  2. spring.redis.database = 2
  3. spring.redis.host = 127.0.0.1
  4. spring.redis.port = 6379
  5. spring.redis.password=
  6. spring.redis.jedis.pool.max-active = 1000
  7. spring.redis.jedis.pool.max-wait = -1
  8. spring.redis.jedis.pool.max-idle = 1000
  9. spring.redis.jedis.pool.min-idle = 0
  10. spring.redis.timeout = 0

2.7、Spring Security

引用失效

如:SecurityProperties.ACCESS_OVERRIDE_ORDER失效,替换为 SecurityProperties._BASIC_AUTH_ORDER _- 2。具具体业务进行替换。

自定义内容

开启 Actuator 安全校验后,为了将用户体系抽里原有体系认证,自定义针对 Actuator 请求连接的特殊处理。(参考连接

2.8、其他

A、jackson 时间戳处理

新版本时间序列化处理,默认为 ISO-8601
旧版本时间序列化处理,默认为 时间戳
沿用旧版本时间戳需要补充添加配置信息 spring.jackson.serialization.write-dates-as-timestamps=true

该配置也会导致 2.1.6 版本的 Spring Boot Admin 中 HttpTrace 界面崩溃问题,解决,参照上面升级信息。

B、Elasticsearch

版本升级,Es 客户端依赖默认到 6.x,不过由于项目本身使用的版本为 7.7.0 ,远高于自带版本,所以无需考虑相关变更。
不过项目运行可能出现报错:NoSuchFieldError: IGNORE_DEPRECATIONS
通过引入依赖解决,依赖如下

  1. <dependency>
  2. <groupId>org.elasticsearch</groupId>
  3. <artifactId>elasticsearch</artifactId>
  4. <version>7.7.0</version>
  5. </dependency>

C、规范包名

自定义 Starter 组件命名规范

D、MVC 上传控制配置变更

  1. # 1.5.x 配置
  2. spring.http.multipart.max-file-size=10MB
  3. spring.http.multipart.max-request-size=10MB
  4. # 高版本: 2.X
  5. spring.servlet.multipart.max-file-size=30MB
  6. spring.servlet.multipart.max-request-size=30MB
  7. # 或者
  8. spring.servlet.multipart.maxFileSize=10MB
  9. spring.servlet.multipart.maxRequestSize=20MB

二、业务服务升级方案

业务系统通过不同的业务职责域将系统切分为不同大小的业务子模块、如:订单模块、用户模块、消息模块等。

每个系统遵循如下的分层架构:
image.png
分管不同业务能力的微服务系统通过 API 的方式对外提供服务能力,需要调用服务的微服务通过引用 API 的方式获得不同的业务能力。

3.1、分层架构升级演进

image.png

如图,通过“绞杀者” 结合 “修缮者”模式对架构进行升级演进。
升级过程

  • 1、保证老版本的 API 保证旧服务的正常引用。
  • 2、提供新版本的 API 为后续升级后的服务提供新的引用API依赖包。
  • 3、所有服务都升级完成后,剔除旧 API 包,完成版本更迭。

其中:通过“绞杀者”模式实现新老 API 引用依赖的更迭。
通过“修缮者”模式对已有的 serverDao/Repository进行修改和调整。

3.1.1、升级方案优点

借助“绞杀者”模式,服务的升级可以按模块进行升级替换。
减少升级周期、以及升级过程中项目需求迭代带来的最小影响。
同时降低升级过程中,由于升级前后,项目引用API版本如:spring boot 等不兼容考虑不周而引起的系统问题。

3.1.2、升级方案缺点

在升级过程中,需要同时维护两套API包。(不过是可以容忍的,代码量较少)。
架构设计中,API包中嵌入了RPC调用,项目中为:Feign 调用,即引用 API 相当于引用了 Feign 相关依赖。而在升级过程中,Feign 新版本 API 不兼容旧版本 API。所以当某个服务升级后,他所依赖的API所在的服务模块也需要进行升级,即升级需要按照最小依赖原则,对服务进行升级。

3.2、升级过程中遇到的问题

问题:循环依赖问题

在梳理项目过程中,发现存在项目间循环依赖问题。
对升级来说,循环依赖导致了,在升级过程中必须针对这些存在循环依赖的项目同时升级的需求,如果循环依赖涉及项目过多,同时部署上线的应用就越多,发生系统问题的概率也会提高。
需要进行依赖解耦合,将依赖降至最低。
如:

  • 引入新服务(如:自定义服务、消息中间件等)将服务解耦。
  • 剔除非必要项目依赖,以及非必要应用间调用