说说我的Spring Boot 3.x微服务升级经历

前言

Spring Boot 3.0 GA版已经发布,好多人也开始尝试升级,有人测试升级后,启动速度确实快了不少,那是因为有Java17和GraalVM加持。那么现在我们能不能把微服务的Spring Boot版本升到3.X呢,这篇文章我来尝试一下,但肯定会碰到各种奇怪问题,不要灰心,毕竟我们只是试试,碰到的问题我们还是可以做个参考的,3.X的升级是迟早的事。

下表示我做的GraalVM、Java 17、Java8 下Spring Boot启动速度比较

VM 包大小 启动时间
GraalVM Native Image 68M 0.15s
Java 17 18M 2.15s
Java 8 16.5M 3.5s

历程

首先就是要把Spring Boot、Spring Cloud 相关的依赖升一下 Spring Boot:3.0.0 Spring Cloud:2022.0.0-RC2

统一依赖版本管理:

<dependencyManagement>
<dependencies>
 <dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-dependencies</artifactId>
  <version>2022.0.0-RC2</version>
  <type>pom</type>
  <scope>import</scope>
 </dependency>
 <dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>3.0.0</version>
  <type>pom</type>
  <scope>import</scope>
 </dependency>
</dependencies>
</dependencyManagement>

现在还不能下载Spring 相关依赖包,需要加入Spring 仓库。在你的maven仓库中加入如下配置,我是加在了pom.xml

<repository>
 <id>netflix-candidates</id>
 <name>Netflix Candidates</name>
 <url>https://artifactory-oss.prod.netflix.net/artifactory/maven-oss-candidates</url>
 <snapshots>
  <enabled>false</enabled>
 </snapshots>
</repository>
<repository>
 <id>spring-milestones</id>
 <name>Spring Milestones</name>
 <url>https://repo.spring.io/milestone</url>
 <snapshots>
  <enabled>false</enabled>
 </snapshots>
</repository>

另外Spring Boot 3.X 开始使用了Java 17,将java版本调整到>17,为了不必要的麻烦,就选17IDEA选择17,并在pom.xml文件中指定版本:

<java.version>17</java.version>

到这里我们的common 包是能正常编译了。

接下来是服务的配置同样调整Spring Boot、Spring Cloud、Java的版本,同common的配置。碰到如下的几个问题:

找不到hystrix的依赖问题:升级后找不到hystrix的版本,官网也找不到,这里我显式指定了版本

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
 <version>2.2.9.RELEASE</version>
</dependency>

rabbitmq问题:相关的配置丢失,比如如下图,这边进行适当调整或者直接注释解决。说说我的Spring Boot 3.x微服务升级经历说说我的Spring Boot 3.x微服务升级经历TypeVariableImpl丢失问题:原来服务中引入了sun.reflect.generics.reflectiveObjects.TypeVariableImpl,现在17中已经被隐藏无法直接使用,这边为了能够先启动,暂时注释,后面再想办法。

Log 异常问题:由于之前我们项目中历史原因,既有用log4j,也有用logback,升级后已经不行,提示冲突,报错如下

Exception in thread "main" java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.helpers.NOPLoggerFactory loaded from file:/Users/chenjujun/.m2/repository/org/slf4j/slf4j-api/1.7.0/slf4j-api-1.7.0.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml: org.slf4j.helpers.NOPLoggerFactory
 at org.springframework.util.Assert.instanceCheckFailed(Assert.java:713)
 at org.springframework.util.Assert.isInstanceOf(Assert.java:632)

意思是,要么移除Logback,要么解决slf4j-api的冲突依赖,这里两种方式都尝试了,slf4j-api依赖的地方太多,后面移除了Logback。

要排除依赖一个好办法:使用Maven Helper插件

说说我的Spring Boot 3.x微服务升级经历
在这里插入图片描述

logback依赖:

<dependency>
 <groupId>ch.qos.logback</groupId>
 <artifactId>logback-classic</artifactId>
 <version>1.2.8</version>
</dependency>

Apollo问题:使用Apollo会提示该错误,需要在启动中加入--add-opens java.base/java.lang=ALL-UNNAMED

Caused by: com.ctrip.framework.apollo.exceptions.ApolloConfigException: Unable to load instance for com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory!
 at com.ctrip.framework.apollo.spring.util.SpringInjector.getInstance(SpringInjector.java:40)
 at com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer.<init>(ApolloApplicationContextInitializer.java:66)
 ... 16 more
Caused by: com.ctrip.framework.apollo.exceptions.ApolloConfigException: Unable to initialize Apollo Spring Injector!
 at com.ctrip.framework.apollo.spring.util.SpringInjector.getInjector(SpringInjector.java:24)
 at com.ctrip.framework.apollo.spring.util.SpringInjector.getInstance(SpringInjector.java:37)
 ... 17 more
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @16612a51
 at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
 at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
 at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
 at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
 at com.google.inject.internal.cglib.core.$ReflectUtils$1.run(ReflectUtils.java:52)
 at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
 at com.google.inject.internal.cglib.core.$ReflectUtils.<clinit>(ReflectUtils.java:42)

通过上述配置调整后,能编译成功,但是无法启动,控制没有任何日志,初步怀疑还是log依赖问题,先不管了,估计是被我搞坏了。

那换个服务试下,下面是我碰到的其他问题。

说说我的Spring Boot 3.x微服务升级经历javax 的依赖都变成jakarta: 比如原来基于javax.validation包中的验证,javax.validation.constraints.NotNull此类的都需要调整

Spring Boot 3.0后,很多starter不能用:Spring Boot 3.0后,以前的spring.factories 不能用了, 只能使用META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports ,对于一些还没改造的starter都无法使用,目前mybatisplus 已经有支持3.0 的 SNAPSHOT版本,其他的druid、nacos 等还适配3.0,要等等了。在我尝试自己改造中间件的starter后还是报错,没招了,因为是中间件内部代码需要改造。

Failed to instantiate [org.springframework.boot.env.EnvironmentPostProcessor]: Specified class is an interface

尝试Over。

总结

总结一下呢,想要把微服务的Spring Boot版本升级还需要较长时间的等待,各种中间件支持需要时间,并且中间件可能还要等其依赖组件支持,整个生态都需要跟进改造。但对于单体的Spring Boot 我觉得是已经可以做一些应用了。


原文始发于微信公众号(阿提说说):说说我的Spring Boot 3.x微服务升级经历

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/101442.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!