Loading

nacos启动异常和动态配置未生效

最近打算研究一下nacos动态配置的原理,于是开始照着Nacos 官网快速入门。但是发现在和SpringBoot以及SpringCloud适配启动的时候,总是报错无法启动,于是深入排查了一下并作以记录。

1. nacos和SpringBoot启动报错

Invalid default: public abstract com.alibaba.nacos.api.config.ConfigType com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource.type()�
翻看源码会发现@NacosPropertySource这个注解的type值是一个不存在的枚举,导致在初始化默认值的时候报错了
image.png

image.png
经排查,发现是ConfigType所属jar包版本过低的原因,从上图可以看出是1.2.1的版本。但是明明我的pom版本中的starter是0.2.12,底层依赖的api版本是2.1.0,为什么实际判定的依然是1.2.1呢?

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.5.0</version>
  </dependency>
  <dependency>
    <groupId>com.alibaba.boot</groupId>
    <artifactId>nacos-config-spring-boot-starter</artifactId>
    <version>0.2.12</version>
  </dependency>
</dependencies>

发现在父项目中,指定了spring-cloud-alibaba-dependencies的版本,虽然我在boot这个模块中没有使用cloud的相关版本,但是由于Maven 父pom中dependencyManagement版本优先级高于传递依赖版本,而spring-cloud-alibaba-dependencies的nacos-api是1.2.1版本,nacos-config-spring-boot-starter下又是传递依赖,最终就以前者为准了。

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
      <version>2.2.1.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

解决方案有两种,一种是在cloud.pom中删掉spring-cloud-alibaba-dependencies,另一种则是在nacos-spring-boot.pom新增依赖,在2.1.0的版本中,nacos-api和nacos-client中都有ConfigType.UNSET这个枚举了

<dependency>
  <groupId>com.alibaba.nacos</groupId>
  <artifactId>nacos-api</artifactId>
  <version>2.1.0</version>
</dependency>
或者
<dependency>
  <groupId>com.alibaba.nacos</groupId>
  <artifactId>nacos-client</artifactId>
  <version>2.1.0</version>
</dependency>

2. nacos和SpringCloud启动报错

Error creating bean with name 'requestMappingHandlerAdapter' defined in class path
......
Caused by: java.lang.ClassNotFoundException: com.fasterxml.jackson.core.StreamReadFeature
单看这个报错,是因为找不到类导致的。
这个项目的pom是这样的,版本也是参考官网的版本

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.2.5.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2.2.1.RELEASE</version>
  </dependency>
</dependencies>

既然是找不到com.fasterxml.jackson.core包里的类,那就观察依赖中的情况,可以明显发现,core包是2.9.10,其他都是2.10.2,直觉告诉我都不太对,那为啥是这样的呢?
image.png
通过idea提供的依赖分析工具来看,jackson-core分别在两个jar包下都存在,只不过在spring-cloud-starter-alibaba-nacos-config中处于第三级,在spring-boot-starter-web中处于第四级,传递依赖里层级越小的优先级越高,所以就以2.9.10为准了
image.png
但这个时候,你可能会疑问,说不是官网推荐的版本吗?怎么会有这样的问题呢?官网的意思是让你总pom使用这个版本,你可以尝试将下面这段加到pom文件中,你会发现就不存在这样的问题了。这是因为在spring-boot-dependencies的下一级就直接定义了jackson-bom的版本为2.10.2.20200130,结合我们问题1中提到的Maven 父pom中dependencyManagement版本优先级高于传递依赖版本,现在起效的就是2.10.2版本了

<dependencyManagement>
  <dependencies>
    <!--            实际上是因为在spring-boot-dependencies定义jackson版本的层级是最近的-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.2.5.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
      <version>2.2.1.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

image.png

3. 启动之后动态配置未生效

先排查nacos和boot或者cloud的版本是否是官方推荐的版本,如果不是,建议先改成推荐版本。
在boot中,核心类是NacosConfigService,如果动态配置一直不生效,可以研究一下是否注册了listener,修改时是否有走到safeNotifyListener
在cloud中,需要额外注意一点是,NacosPropertySourceLocator这个bean是否有被实例化,他在NacosConfigBootstrapConfiguration中。如果NacosPropertySourceLocator没有实例化,启动时根本不会拉取nacos云上的配置。

posted @ 2024-05-23 11:57  起司啊  阅读(62)  评论(0编辑  收藏  举报