作者 | 张乐、张皓天
Spring Framework 6.0 已于11月份上旬正式发布 GA 版本。Spring Boot 3.0 也于11月25日正式发布 GA 版本。那么 Spring Cloud 2022 它还远吗?
前言
Java 8 目前是国内主流生产环境 Java 版本之一。虽然近几年陆续发布了 Java 11、Java 17 官方 LTS 版本,但是 “你发任你发,我用Java8” 的声音反应了大部分开发者的心声。不过 Java 17 版本在性能上做了大量的优化特别是 ZGC 的发布,促进了国内不少企业升级到 Java 17。
Spring 在 Java 语言的作用不言而喻,Spring Framework 5.0 发布已至今五年,是时候需要一个大的版本来革新技术栈了。借着 Java 17 的东风我们认为
“Java 17 + Spring Framework 6.0 + Spring Boot 3.0 + Spring Cloud 2022”
组合一定会在不久的将来被大家所接受,成为主流技术栈。当然任何新技术大规模被认可、落地都会有一定的滞后性,技术的发展 “稳”字当头。
Spring Cloud Tencent 是基于腾讯开源的一站式微服务平台北极星(集服务注册发现、配置中心、服务限流熔断、服务路由于一身)实现的 Spring Cloud 微服务解决方案套件。真正做到 “All In One”、 开箱即用,极大的降低企业的微服务实践门槛。
无论北极星还是 Spring Cloud Tencent 当前都在积极的修复 Bug、完善用户体验、迭代新功能。所以 Spring Cloud Tencent 也第一时间适配了 Spring Cloud 2022 版本。此篇文章详细讲述了 Spring Cloud Tencent 从 2021 版本升级到 2022 版本的改动点,为尝鲜 2022 版本的广大开发者提供一些参考。
一、升级过程
1.1 升级安装 JDK 17
Oracle 官网下载 JDK 17 并安装。安装之后,本地修改 JAVA_HOME 环境变量,如下以我的 Mac 为例:
#echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk-17.0.5.jdk/Contents/Home
#java -version
java version "17.0.5" 2022-10-18 LTS
Java(TM) SE Runtime Environment (build 17.0.5+9-LTS-191)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.5+9-LTS-191, mixed mode, sharing)
安装好 JDK 17 之后,同时需要在 Idea 里设置项目的编译和运行环境为 SDK 17。
1.2 升级依赖版本
Spring Cloud Tencent 项目引用的 Parent Pom 是 spring-cloud-build,所以需要升级到最新版本。
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>4.0.0-RC2</version>
<relativePath/>
</parent>
可以看到 Spring-cloud-build 4.0.0-RC2 版本里定义的 Java 和 Spring Boot 版本已是最新的 Java 17 和 Spring Boot 3.0
<properties>
<java.version>17</java.version>
<spring-boot.version>3.0.0-RC2</spring-boot.version>
</properties>
普通项目一般不需要继承 spring-cloud-build ,而是通过 bom 的方式引入 Spring 全家桶。如果你的项目里定义了 Java、Spring Framework、Spring Boot、Spring Cloud 版本则需要同时升级。如下所示:
<properties>
<java.version>17</java.version>
<spring.framework.version>6.0.1</spring.framework.version>
<spring-boot.version>3.0.0</spring-boot.version>
<spring.cloud.version>2022.0.0-RC2</spring.cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring Framework Dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>${spring.framework.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Boot Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
注意:Spring 非 GA 版本会先发布到 Spring 自己的 Maven 仓库,而不会发布到中央仓库。所以如果拉不到包 ,则需要在项目根 Pom 或者本地 ~/.m2/settings.xml 里配置 Spring Maven 仓库。
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
在升级过程中,大概率会出现包冲突的情况,例如 SCT 在升级过程中发现日志依赖有问题导致 example 启动失败。最后排查到原因:SCT 自己定义了 logback版本为 1.2.11,但是升级 Spring Boot 3.0 里传递依赖的版本为 1.4.5,所以导致版本冲突。最后解决方案就是把 SCT 定义的版本去掉,只用传递依赖的版本。
Tips:解决版本冲突大概率会占用比较多的时间,升级过程需要有耐心 😭
1.3 修改不兼容代码
javax 包替换为 jakarta 包
这是Java17 最大变更点之一,代码所有 import javax 都要替换为 jakarta。编译不通过的地方直接通过 Idea 自动导入的方式变更即可。
spring-web 6.0 不兼容升级
SCT 在升级过程中发现 spring-web 包下有些 API 不兼容,例如 ClientHttpResponse.getStatusCode() 老版本返回 HttpStatus,新版本返回的是 HttpStatusCode,改动量很小。
AutoConfiguration 自动装配方式变更
在 Spring Boot 3.0 以前的版本,通过在 META-INF/spring.factories 文件中定义需要自动装配类,Spring Boot 在启动过程中就会执行装配 Bean,如下所示:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.tencent.cloud.plugin.pushgateway.PolarisStatPushGatewayAutoConfiguration
但是在 Spring Boot 3.0 中,则是通过在
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件定义需要自动装配的类。所以迁移过程就是把org.springframework.boot.autoconfigure.EnableAutoConfiguration 下配置的类都放到新的文件中。
这里需要注意的是原来在 spring.factories 可以定义多种类型的自动装配例如:
-
org.springframework.boot.autoconfigure.EnableAutoConfiguration
-
org.springframework.cloud.bootstrap.BootstrapConfiguration
-
org.springframework.context.ApplicationListener
-
... ...
只需要把 org.springframework.boot.autoconfigure.EnableAutoConfiguration 部分迁移到 org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,其它部分还是放在 spring.factories 中无需迁移。
至此 SCT 2022 升级适配工作即已完成,可以看出升级工作量并不大。
1.4 升级总结
SCT 属于比较底层的基础框架组件,依赖的第三方库少,所以整体适配工作量较少。如果您的应用是上层业务应用依赖了大量的组件,例如: spring-security、spring-stream等。那升级的成本也会高很多。
下面是 github 网友 @herodotus-cloud 总结的升级关键点:
-
更换 JDK 17 后,少部分第三方依赖包版本选择和控制问题
-
新依赖包过时代码替换。大多数没问题,就怕遇到像 spring security 6 用法的变化
-
starter 自动配置注册格式不同导致的,大多数第三方依赖都倒在这里
-
最怕的就是核心机制的变化,比如说反射。好像一些反射在 JDK 17 会有问题
-
最大的问题就是基础设置组件升级不同步或者缓慢问题,比如依赖的某个 SDK 没有升级 SDK 17,如果传递依赖了就会导致编译问题。
-
如果还要考虑向下的兼容性,怕就难了
Spring 官方建议先升级到 Spring Boot 2.7 小版本,然后再升级到 Spring Boot 3.0 版本。通过小步升级的方式,可以更加的平滑。
二、尝鲜使用 Spring Cloud Tencent 2022.0 版本
Spring Cloud Tencent 1.8.1-2022.0.0-RC2 版本已发布。通过引入 SCT BOM 的方式即可引入,如下所示:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId>
<version>1.8.1-2022.0.0-RC2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
在此解释一下 SCT 的版本号规则,版本号分为两段:
${SCT 版本}-${对应的 Spring Cloud 版本}
SCT 版本号在各个 Spring Cloud 版本之间对齐,例如 1.8.1-Hoxton.SR12 和 1.8.1-2022.0.0-RC2 ,SCT 版本号都是 1.8.1,功能完全对齐,只是引用的 Spring Cloud 不同。1.8.1-Hoxton.SR12 对应的是 Spring Cloud Hoxton.SR12 版本,而 1.8.1-2022.0.0-RC2 对应的是2022.0.0-RC2 版本。版本号中引入 Spring Cloud 版本为了一眼就能识别 Spring Cloud 版本对应关系。开发者优先选择跟自己版本一致的 Spring Cloud 版本,再选择最新的 SCT 版本。
使用 SCT 各个子模块的功能,请参考 SCT Github Wiki 文档。
三、 呼吁
第三方基础组件的升级节奏会直接影响上层应用的升级,在此也呼吁第三方基础组件的维护者能够尽快跟进适配。为广大愿意尝鲜的开发者和企业提供便利。
四、欢迎共建
如果您对微服务、Spring Cloud 技术感兴趣,欢迎加入我们。您的一个建议、Issue、Pull Request 甚至只是一个小小的 Star 都是对 Spring Cloud Tencent 社区极大的支持。
SCT Github 地址:https://github.com/Tencent/spring-cloud-tencent
北极星官网:https://polarismesh.cn/