1. 升级背景与效果概述
最近完成了从JDK8到JDK21的升级,同时将SpringCloud全家桶进行了版本更新。实测效果非常显著:系统内存占用降低了50%,启动速度提升了40%。这样的性能提升对于我们的微服务架构来说意义重大,特别是在高并发场景下,资源利用率的优化直接降低了服务器成本。
这次升级涉及的核心组件版本如下:
- SpringBoot 3.5.5
- SpringCloud 2025.0.0和4.3.0
- SpringCloudAlibaba 2023.0.3.3
- Knife4j 4.5.0
- MyBatis-Plus 3.5.14
特别需要注意的是,从JavaEE到JakartaEE的迁移是这次升级的关键点之一。所有javax.servlet的引用都需要改为jakarta.servlet,这个改动会影响很多基础组件。
2. 环境准备与依赖管理
2.1 JDK21环境配置
首先需要在开发环境和构建工具中配置JDK21。在Maven的pom.xml中需要明确指定Java版本:
xml复制<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
注意:JDK21是长期支持版本(LTS),相比JDK17又带来了多项性能改进,包括虚拟线程(Project Loom)、分代ZGC等特性。这些新特性是性能提升的关键。
2.2 依赖版本管理
完整的依赖版本管理配置如下:
xml复制<properties>
<!-- 核心框架版本 -->
<spring.boot.version>3.5.5</spring.boot.version>
<spring-cloud-dependencies.version>2025.0.0</spring-cloud-dependencies.version>
<spring-cloud-alibaba-dependencies.version>2023.0.3.3</spring-cloud-alibaba-dependencies.version>
<!-- 常用工具库版本 -->
<hutool.version>5.8.24</hutool.version>
<commons-lang3.version>3.8</commons-lang3.version>
<!-- 数据库相关 -->
<mybatis-plus-boot-starter-version>3.5.14</mybatis-plus-boot-starter-version>
<druid.version>1.2.27</druid.version>
<!-- 其他组件 -->
<knife4j.version>4.5.0</knife4j.version>
<xxl-job.version>2.2.0</xxl-job.version>
<caffeine.version>2.9.3</caffeine.version>
</properties>
3. 核心组件升级详解
3.1 SpringBoot 3.x升级要点
SpringBoot从2.x升级到3.x有几个关键变化:
-
Jakarta EE 9+支持:所有javax包名都改为jakarta
- 需要全局替换import语句
- 影响较大的包包括:servlet、persistence、validation等
-
JDK基线要求:
- SpringBoot 3.x最低要求JDK17
- 我们直接升级到JDK21以获得最佳性能
-
自动配置变化:
- 部分自动配置类路径发生了变化
- 需要检查自定义的自动配置类是否需要调整
3.2 SpringCloud 2025.0.0兼容性
SpringCloud 2025.0.0与SpringBoot 3.5.5的兼容性矩阵需要特别注意:
| 组件 | 兼容版本 |
|---|---|
| Spring Cloud Gateway | 4.3.0 |
| Spring Cloud OpenFeign | 4.3.0 |
| Spring Cloud Sleuth | 3.2.0 |
实际使用中发现,SpringCloud 2025.0.0与某些Alibaba组件的兼容性需要特别测试,建议在测试环境充分验证。
3.3 数据库相关组件升级
MyBatis-Plus升级到3.5.14版本后,有几个重要改进:
- 分页插件优化:新的分页实现性能更好
- Lambda表达式增强:类型推断更智能
- 与JDK21的兼容性:修复了在高版本JDK下的几个潜在问题
配置示例:
xml复制<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus-boot-starter-version}</version>
</dependency>
4. 常见问题与解决方案
4.1 兼容性问题排查
在升级过程中遇到的主要问题及解决方案:
-
Jakarta包名冲突:
- 现象:NoClassDefFoundError或ClassNotFoundException
- 解决:使用Maven的exclusion排除旧的javax依赖
- 示例:
xml复制<exclusions> <exclusion> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </exclusion> </exclusions>
-
反射API变化:
- JDK21加强了模块化限制
- 需要在启动参数添加:
code复制--add-opens java.base/java.lang=ALL-UNNAMED
4.2 性能调优建议
基于实际测试结果,推荐以下配置优化:
-
JVM参数调整:
code复制-XX:+UseZGC -Xms512m -Xmx512m- ZGC在JDK21中已经成为生产就绪的GC
- 内存设置应根据实际负载调整
-
SpringBoot优化:
properties复制spring.main.lazy-initialization=true spring.jmx.enabled=false -
MyBatis-Plus缓存:
java复制@Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }
5. 升级后的监控与验证
5.1 性能指标对比
升级前后的关键指标对比:
| 指标 | 升级前 | 升级后 | 提升幅度 |
|---|---|---|---|
| 启动时间(ms) | 4500 | 2700 | 40% |
| 内存占用(MB) | 1024 | 512 | 50% |
| 吞吐量(QPS) | 1200 | 1800 | 50% |
5.2 监控配置建议
推荐使用以下监控组合:
-
Prometheus + Grafana:
xml复制<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> <version>${io.micrometer.version}</version> </dependency> -
SpringBoot Actuator:
properties复制management.endpoints.web.exposure.include=health,info,metrics,prometheus management.metrics.export.prometheus.enabled=true -
日志收集:
- 推荐使用Logstash或Fluentd收集日志
- 配合ELK或Loki进行日志分析
6. 回滚策略与应急预案
尽管升级带来了显著的性能提升,但必须准备完善的回滚方案:
-
代码回滚点:
- 在升级前创建单独的分支
- 每个微服务单独升级和回滚
-
数据库兼容性:
- 确保ORM框架的兼容性
- 准备数据库回滚脚本
-
容器化部署:
dockerfile复制FROM eclipse-temurin:21-jre-jammy COPY target/app.jar /app.jar ENTRYPOINT ["java","-jar","/app.jar"]- 保留旧版本的Docker镜像
- 使用蓝绿部署策略降低风险
在实际操作中,我们采取了分阶段升级策略:先在一个非核心服务上验证,然后逐步推广到全站。整个过程持续了两周时间,期间密切监控各项指标,确保系统稳定性。