一、简述
1.文章由来
公司内部一直使用1.5.9.RELEASE版本的springboot,今年计划升级到2.x版本,本人在其中一个项目中升到到2.x并在生产上使用约4个月后整理了一些经验,在研发部进行分享。原稿改编后整理在博客中。
2.升级原因
1.直接原因:log4j存在危险的安全漏洞,需要升级log4j版本。springboot1.5.9.RELEASE版本默认用的是2.7版本的log4j,替换为2.8.2之后的版本或者升级springboot版本可以解决问题。
2.版本过旧,有些已经闭源,或存在历史漏洞。1.5.9.RELEASE是2017年11月份发行,截止到现在,已经验证出许多漏洞,并通过版本升级修复了漏洞。
公司的devops平台的流水线构建时通过HUB扫描发现,历史版本有许多中高级的安全漏洞,必须升级修复。
3.新版本有很多有用的特性。
比如:2.x版本默认使用当前java中性能最好的HikariCP做数据库连接池。https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Configuration-Changelog
3.同步升级spring-cloud
springboot升级,依赖的spring也会随之升级。此外,springcloud版本需要和springboot兼容,在springboot版本升级比较大的情况下,也可能需要升级。
参考:springboot-springcloud版本对应表:https://start.spring.io/actuator/info
推荐项目使用的版本:
springboot | springcloud | spring | |
---|---|---|---|
升级前 | 1.5.9.RELEASE | Edgware.SR1 | 4.3.13.RELEASE |
升级后 | 2.1.5.RELEASE | Greenwich.SR3 | 5.1.7.RELEASE |
二、解决版本变化遇到的问题
新旧版本有许多设计上的变化,如果不一一检查,并做相应改动,将导致许多程序问题!
每个项目使用的组件,配置各不相同,尽量使用下面方式逐一检查。
1.根据使用的技术栈,查看官方的指导,检验是否有变动
根据关键字搜索github中官方文档(https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide),示例,redis相关:
目前使用的常用中间件需要关注的信息:
数据库: mysql、数据库连接池
搜索引擎: elasticsearch
nosql: redis
mq: rabbitmq、kafka
2.检查配置变化
配置变动的情况有
1.属性key变化。
2.属性value默认值有变化。
3.属性value单位发生变化。 例如:server.connection-timeout=10需要写成server.connection-timeout=10ms
(1)根据已有的配置,查看官方的指导,检验是否有变动
根据关键字搜索github中官方文档(https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Configuration-Changelog),示例,服务上下文配置相关:
(2)使用IDEA检验是否正确
将配置文件(yml、properties格式)拷贝到IDEA
示例:
springboot的自动化配置中,不包含spring.application.names属性,所以会标注警告信息
2.解决包依赖的版本冲突
包冲突的后果:
- 编译报错
- 项目无法正常启动,因为类结构可能有变化
- 项目可启动,运行中项目程序出错,因为有些类运行时才能执行
解决办法:
查看包依赖的版本,exclude包或者删除包依赖。注意:并非排除了冲突的包就能解决问题,因为可能解决了A代码缺少的类,但是导致了B代码缺失了类。
IDEA安装maven-helper插件,找到xxx-service模块的pom.xml文件
三、常见的改变汇总
1.应用上下文路径
server.context-path改为server.servlet.context-path
2.eureka和feign的坐标变化
(1)feign
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
改为
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
@FeignClient和@EnableFeignClients包名变了,需要重新import
(2)eureka-client
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
改为
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(3)eureka-server
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
改为
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
(4)hystrix
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
改为
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
3.feign调用超时设置
1.5.9.RELEASE
ribbon.ReadTimeOut=10000
ribbon.ConnectTimeout=10000
2.x.RELEASE
feign.client.default.readTimeout=10000 feign.client.default.connectTimeout=10000
参考:Spring Cloud组件那么多超时设置,如何理解和运用? https://www.jianshu.com/p/c836a283631e
4.log4j2
我们使用的日志组件是log4j2
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
springboot-1.5.9.RELEASE版本的log4j2版本是2.7,而2.x以上版本至少是2.10.0版本
5.数据库连接池
springboot-1.5.9.RELEASE版本默认连接池用的是tomcat-jdbc,2.x版本用的是性能更好的HikariCP连接池
springboot-1.5.9.RELEASE版本,用spring.datasource.tomcat开头的参数配置连接池,示例
### 数据库连接配置
spring.datasource.tomcat.test-on-borrow = false
spring.datasource.tomcat.test-while-idle = true
spring.datasource.tomcat.time-between-eviction-runs-millis = 3600000
spring.datasource.tomcat.max-active=30
springboot-2.x.RELEASE版本,用spring.datasource.hikari开头的参数配置连接池,示例
### 数据库连接配置
# 最小空闲连接数,默认是10
spring.datasource.hikari.minimum-idle=5
## 连接池最大连接数,默认是10
spring.datasource.hikari.maximum-pool-size=15
可参考官方配置:https://github.com/brettwooldridge/HikariCP
注意:
1.HikariCP的作者推荐使用hikaricp的默认配置即可,因为作者对连接池的默认配置是经过大量优化得出的。如果有特殊的情况,可参考作者的建议:https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
2.重要:不推荐只设置maximum-pool-size而不设置minimum-idle,因为maximum-pool-size一般是用来提供给突然的高并发而设置的。但如果当设置maximum-pool-size,而没有设置minimum-idle,系统会自动设置minimum-idle=maximum-pool-size,这样会导致应用从启动开始,一直保持maximum-pool-size大小的数据库连接,如果应用本不需要这么多连接,会浪费连接,而导致数据库连接数不够用。
6.上传附件的大小控制配置
spring.http.multipart.max-file-size=20mb spring.http.multipart.max-request-size=30mb
改为
spring.servlet.multipart.max-file-size=20mb spring.servlet.multipart.max-request-size=30mb
7.redis客户端
# boot1.x配置
spring:
datasource:
redis:
database: 0 # Database index used by the connection factory.
timeout: 0 # Connection timeout in milliseconds.
pool: # 默认使用jedis客户端
max-active: 8 #
max-idle: 8 #
max-wait: -1 #
min-idle: 1 #
#boot2.x配置
spring:
redis:
database: 0 # Database index used by the connection factory.
timeout: 0 # Connection timeout in milliseconds.
lettuce: # 默认使用lettuce客户端,如果需要使用jedis客户端,需要修改pom.xml
pool:
max-active: 8 #
max-idle: 8 #
max-wait: -1 #
min-idle: 1 #
如果需要改为jedis客户端,需要配置pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<!-- 1.5的版本默认采用的连接池技术是jedis 2.0以上版本默认连接池是lettuce, 在这里采用jedis,所以需要排除lettuce的jar -->
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--spring2.0集成redis所需common-pool2-->
<!-- 必须加上,jedis依赖此 -->
<!-- spring boot 2.0 的操作手册有标注 大家可以去看看 地址是:https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/htmlsingle/-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.5.0</version>
</dependency>
8.eureka注册中心
eureka的server与client采用http方式通信,所以eureka的server可以不用升级,但最好server一起升级,方便未来进行扩展。
未来会换用consul注册中心,因为eureka已经停止维护并且偶尔有异常报错的情况。
9.监控检查地址
如果依赖了spring-boot-actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
原来的健康检查地址有变动,最常用的/info和/health已改为/actuator/info和/actuator/health.
影响:
应用监控的健康检查策略如果是:如果配置的是/info或者/health,需要修改为新的地址,不然应用启动后后,探针访问/info或/health地址后会报404,认为是启动失败。
四、建议
1.尽量早做,在项目迭代中预留足够的测试时间,升级的坑可能要测试较长一段时间后才能发现。
2.后端开发修改完配置后,要评估影响范围,并告知测试人员,一起进行回归测试。