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值是一个不存在的枚举,导致在初始化默认值的时候报错了
经排查,发现是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,直觉告诉我都不太对,那为啥是这样的呢?
通过idea提供的依赖分析工具来看,jackson-core分别在两个jar包下都存在,只不过在spring-cloud-starter-alibaba-nacos-config中处于第三级,在spring-boot-starter-web中处于第四级,传递依赖里层级越小的优先级越高,所以就以2.9.10为准了
但这个时候,你可能会疑问,说不是官网推荐的版本吗?怎么会有这样的问题呢?官网的意思是让你总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>
3. 启动之后动态配置未生效
先排查nacos和boot或者cloud的版本是否是官方推荐的版本,如果不是,建议先改成推荐版本。
在boot中,核心类是NacosConfigService,如果动态配置一直不生效,可以研究一下是否注册了listener,修改时是否有走到safeNotifyListener
在cloud中,需要额外注意一点是,NacosPropertySourceLocator这个bean是否有被实例化,他在NacosConfigBootstrapConfiguration中。如果NacosPropertySourceLocator没有实例化,启动时根本不会拉取nacos云上的配置。