简单记录由于Nacos导致的Spring BootSpring Cloud版本不兼容的原因分析过程。

在Python程序中使用Nacos这篇文章中我吐槽了Nacos,今天我还要继续吐槽Nacos

Why? 因为Nacos中的一个jar包引入了错误的spring-cloud-commons依赖,导致Spring Boot程序启动时出现版本不兼容问题,启动失败,浪费了我好几个小时的时间(虽然这样显得我很不专业)!

问题

自己准备将网关项目加入Nacos的服务管理和配置管理功能,依照官方文档的说明添加了com.alibaba.cloud相关的依赖,pom.xml文件中的完整配置如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.lucumt</groupId>
  <artifactId>spring-gateway-test</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>spring-gateway-demo</name>
  <url>https://lucumt.info</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <spring.boot.version>2.7.3</spring.boot.version>
    <spring.cloud.version>3.1.3</spring.cloud.version>
    <spring.cloud.alibaba.version>2021.1</spring.cloud.alibaba.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-dependencies</artifactId>
      <version>2021.0.8</version>
      <type>pom</type>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
      <version>${spring.cloud.alibaba.version}</version>
      <type>pom</type>
    </dependency>
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
      <version>${spring.cloud.alibaba.version}</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
      <version>${spring.cloud.alibaba.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-bootstrap</artifactId>
      <version>${spring.cloud.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>${spring.boot.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <version>${spring.boot.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>${spring.boot.version}</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.24</version>
      <scope>provided</scope>
    </dependency>

  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <version>${spring.boot.version}</version>
        <executions>
          <execution>
            <goals>
              <goal>repackage</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

</project>

启动该程序后控制台提示如下错误,程序启动失败!

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-09-01 21:02:30.144 ERROR 20760 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Your project setup is incompatible with our requirements due to following reasons:

- Spring Boot [2.7.3] is not compatible with this Spring Cloud release train


Action:

Consider applying the following actions:

- Change Spring Boot version to one of the following versions [2.3.x, 2.4.x] .
You can find the latest Spring Boot versions here [https://spring.io/projects/spring-boot#learn]. 
If you want to learn more about the Spring Cloud Release train compatibility, you can visit this page [https://spring.io/projects/spring-cloud#overview] and check the [Release Trains] section.
If you want to disable this check, just set the property [spring.cloud.compatibility-verifier.enabled=false]

分析

根据上述报错提示信息去https://spring.io/projects/spring-cloud#overview中去查看Release Train:

Spring Clould Release Train

进一步的查看上图中标红的版本结果如下,可发现Spring Cloud中主要的模块版本都为3.1.x系列。

Spring Clould 2021.08 Release

而我自己项目中Spring BootSpring Cloud的版本定义如下,明明符合上图中的版本对应关系,为啥还是报错呢?

<spring.boot.version>2.7.3</spring.boot.version>
<spring.cloud.version>3.1.3</spring.cloud.version>

虽然可通过提示说明spring.cloud.compatibility-verifier.enabled=false来暂时规避掉此问题,但我还是很好奇为啥明明版本对应上了,实际上却依然报错?

遇到这种问题自己的第一反应是通过GoogleStackoverflow去查找,但并没有找到有用信息。

之后根据提示尝试将SpringBoot版本降低到2.3.x2.4.x,依然未能解决问题。

没办法我只能采用终极大招通过二分法查找定位!将Nacos相关的依赖都去掉,然后逐步添加回去,最终发现是spring-cloud-starter-alibaba-nacos-config导致的,之后再次去Google一番,依旧没能找到原因。

怎么办?

突然间想到将日志级别设置为DEBUG是否能找到一些有用的信息呢?说干就干,bootstrap.yaml文件中添加如下配置

logging:
  level:
    root: DEBUG

重新启动后控制台虽然依旧报错,但提示信息更详细,从中我们可找到如下信息:

org.springframework.cloud.configuration.CompatibilityNotMetException: null
	at org.springframework.cloud.configuration.CompositeCompatibilityVerifier.verifyDependencies(CompositeCompatibilityVerifier.java:47) ~[spring-cloud-commons-3.0.1.jar:3.0.1]
	at org.springframework.cloud.configuration.CompatibilityVerifierAutoConfiguration.compositeCompatibilityVerifier(CompatibilityVerifierAutoConfiguration.java:44) ~[spring-cloud-commons-3.0.1.jar:3.0.1]

很明显版本不兼容是由spring-cloud-common导致的,在命令行执行mvn dependency:tree -Dincludes="org.springframework.cloud:spring-cloud-commons"输出结果如下

[INFO] com.lucumt:spring-gateway-test:jar:1.0-SNAPSHOT
[INFO] \- com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config:jar:2021.1:compile
[INFO]    \- org.springframework.cloud:spring-cloud-commons:jar:3.0.1:compile

可以看出确实是由于spring-cloud-starter-alibaba-nacos-config包引入后导致的。

Maven中央仓库中查看该版本对应的jar包依赖结果如下,spring-cloud-commons的依赖版本确实是3.0.1,与前述分析结果一致。

Spring Clould Nacos依赖

解决

找到问题原因后,解决起来很简单,在pom.xml文件中手工指定spring-cloud-commons的依赖并下载即可:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-commons</artifactId>
    <version>${spring.cloud.version}</version>
</dependency>

反思

虽然此问题的原因和解决方案都不复杂,但我在此问题上浪费了好几个小时感觉很不划算,本着严于律己,宽以待人的原则主要问题还是出在自己身上:没有早点开启DEBUG日志模块,早点打开就能早发现,自己没有形成相关的问题排查方法论。