Client-NacosConfigService 再分析

本文深入探讨了Nacos客户端的核心组件ServerHttpAgent和ClientWorker,特别是ServerListManager如何获取Nacos服务器列表。客户端通过定时任务每10毫秒检查配置,对比服务器与本地配置的差异。配置更新主要发生在addListener时,而ClientWorker的cacheMap更新关键在于监听器的注册。若未注册监听器,客户端将依赖checkConfigInfo方法检测配置变更。ConfigFailoverFile的存储格式为每个配置项一个文件,存储路径为${envName}

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明:本篇文章部分内容参考了网上的文章(在下文已给出原文链接),由于本人能力有限,如果有书写错误的地方,欢迎各位大佬批评指正!我们互相交流,学习,共同进步!

该项目的地址:https://github.com/xiaoheng1/nacos_read

先看下 Client 端 NacosConfigService 的核心组件:
在这里插入图片描述

两大核心组件:ServerHttpAgent 和 ClientWorker.

需要注意的是,在 ServerHttpAgent 中,有一个 ServerListManager 成员变量. 这个类就是为了获取 nacos server 服务列表.

现在支持两种方式,一种是固定 ip 的,另一种是从服务器获取 nacos server 列表.

需要注意的是,在 ServerHttpAgent 中,有一个 ServerListManager 成员变量. 这个类就是为了获取 nacos server 服务列表.

现在支持两种方式,一种是固定 ip 的,另一种是从服务器获取 nacos server 列表.

在 ClientWorker 中,起了一个定时任务,每 10 毫秒执行一次,调用 checkConfigInfo 方法.

对比 client 端缓存的配置和 server 端的配置是否一致,默认情况下一次对比 3000 条.

那么问题来了?ClentWorker 中的 cacheMap 是什么时候更新的了?

一步步追踪,最后发现是在 addListener 的时候.

public void addListener(String dataId, String group, Listener listener) throws NacosException {
worker.addTenantListeners(dataId, group, Arrays.asList(listener));
}

那么问题来了?如果客户端不注册 listener,能否收到 server 主动推送的 config change 通知了?

按照现有逻辑,应该是只能依赖 checkConfigInfo 这个方法的检查才能收到通知.

addListener/removeListener 会导致 ClientWorker 中 cacheMap 的变化.

所以,对于 client config server 而言,核心点有两个,一个是访问 server 进行发布配置、删除配置等操作,另一个是 ClientWorker.

ClientWorker.run(){

// 1.check failover config
// 优先用 failover file 来更新 cacheData.
checkLocalConfig()
// 如果 md5 发生改变,则通知 listener.
checkListenerMd5()

// 2.check server config
// 从 cacheData 中找 isUseLocalConfigInfo=false 的数据,拼接 dataId、group 等, 调用 checkUpdateConfigStr 方法.
checkUpdateDataIds()
// 在这个方法中,会向 nacos server 发送 http 请求. /v1/cs/configs/listener. 那么问题来了?向那一台发起请求了?
// 在 ServerListManager 中有一个属性:currentServerAddr. 向这台服务器发送请求.
// 如果请求 nacos server 成功,那么会解析结果, 返回更新的集合.
checkUpdateConfigStr()

// 3.拿到 2 的 changedGroupKeys 后,进行遍历.
// 向 /v1/cs/configs 发起请求,请求成功后,会将配置保存到 snapshot.
// 一个配置项一个文件.
// 这里使用的是 agent.getName() 和 failover 的那个名称是一致的.
// LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, result.getData());
// 更新 cacheData.
// 通知 cacheData 上的 listener.

// 4.将这个任务再加入到 executorService 中.

}

问题:config failover file 是在哪保存的?存储格式是什么?

1.存储格式很简单,就是一个配置项一个文件.
2.存储文件名:${envName}_nacos/snapshot/group/dataId

接着看下 com.alibaba.nacos.config.server.controller.ConfigController#listener

如果支持长轮询的话,就等待,否则就直接比较.

com.alibaba.nacos.config.server.utils.MD5Util#compareMd5 只要 client 的某个 key 的 md5 和 server 的 md5 不一致,说明发生了改变.

传送到 server 端的 key:

dataId|group|md5|tenant,xxxxxx

clientMd5Map key is group key(dataId|groupId|tenant), value is md5.

compareMd5OldResult & compareMd5ResultString 应该是处理兼容问题.

G:\jdk\bin\java.exe -Dspring.application.name=ecust-custom-api-li -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true "-Dmanagement.endpoints.jmx.exposure.include=*" "-javaagent:G:\2025.1\IntelliJ IDEA 2025.1\lib\idea_rt.jar=56586" -Dfile.encoding=UTF-8 -classpath C:\Users\Administrator\AppData\Local\Temp\classpath458130718.jar com.ruoyi.customApi.OuchnCustomApiApplication 19:27:39.566 [background-preinit] INFO o.h.v.i.util.Version - [<clinit>,21] - HV000001: Hibernate Validator 6.2.3.Final 19:27:39.825 [main] INFO c.u.j.c.EnableEncryptablePropertiesBeanFactoryPostProcessor - [postProcessBeanFactory,40] - Post-processing PropertySource instances 19:27:39.825 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,76] - Skipping PropertySource configurationProperties [class org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertySource 19:27:39.827 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource bootstrap [org.springframework.core.env.MapPropertySource] to EncryptableMapPropertySourceWrapper 19:27:39.827 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource systemProperties [org.springframework.core.env.PropertiesPropertySource] to EncryptableMapPropertySourceWrapper 19:27:39.827 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource systemEnvironment [org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource] to EncryptableSystemEnvironmentPropertySourceWrapper 19:27:39.828 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource random [org.springframework.boot.env.RandomValuePropertySource] to EncryptablePropertySourceWrapper 19:27:39.828 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource cachedrandom [org.springframework.cloud.util.random.CachedRandomPropertySource] to EncryptablePropertySourceWrapper 19:27:39.828 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource springCloudClientHostInfo [org.springframework.core.env.MapPropertySource] to EncryptableMapPropertySourceWrapper 19:27:39.828 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource Config resource 'class path resource [bootstrap.yml]' via location 'optional:classpath:/' [org.springframework.boot.env.OriginTrackedMapPropertySource] to EncryptableMapPropertySourceWrapper 19:27:39.854 [main] INFO c.u.j.f.DefaultLazyPropertyFilter - [lambda$new$2,31] - Property Filter custom Bean not found with name 'encryptablePropertyFilter'. Initializing Default Property Filter 19:27:39.864 [main] INFO c.u.j.r.DefaultLazyPropertyResolver - [lambda$new$2,35] - Property Resolver custom Bean not found with name 'encryptablePropertyResolver'. Initializing Default Property Resolver 19:27:39.865 [main] INFO c.u.j.d.DefaultLazyPropertyDetector - [lambda$new$2,35] - Property Detector custom Bean not found with name 'encryptablePropertyDetector'. Initializing Default Property Detector Spring Boot Version: 2.6.6 Spring Application Name: ecust-custom-api-li _ _ (_) | | _ __ _ _ ___ _ _ _ ______ ___ _ _ ___ | |_ ___ _ __ ___ | '__|| | | | / _ \ | | | || ||______|/ __|| | | |/ __|| __| / _ \| '_ ` _ \ | | | |_| || (_) || |_| || | \__ \| |_| |\__ \| |_ | __/| | | | | | |_| \__,_| \___/ \__, ||_| |___/ \__, ||___/ \__| \___||_| |_| |_| __/ | __/ | |___/ |___/ 19:27:40.172 [main] INFO c.a.n.c.r.client - [lambda$createClient$0,80] - [RpcClientFactory] create a new rpc client of 10025a0f-383b-4399-95f8-7c31d45f15a5_config-0 19:27:40.196 [main] INFO o.r.Reflections - [scan,232] - Reflections took 15 ms to scan 1 urls, producing 3 keys and 6 values 19:27:40.212 [main] INFO o.r.Reflections - [scan,232] - Reflections took 8 ms to scan 1 urls, producing 4 keys and 9 values 19:27:40.220 [main] INFO o.r.Reflections - [scan,232] - Reflections took 7 ms to scan 1 urls, producing 3 keys and 10 values 19:27:40.230 [main] INFO o.r.Reflections - [scan,232] - Reflections took 8 ms to scan 14 urls, producing 0 keys and 0 values 19:27:40.237 [main] INFO o.r.Reflections - [scan,232] - Reflections took 6 ms to scan 1 urls, producing 1 keys and 5 values 19:27:40.246 [main] INFO o.r.Reflections - [scan,232] - Reflections took 7 ms to scan 1 urls, producing 1 keys and 7 values 19:27:40.258 [main] INFO o.r.Reflections - [scan,232] - Reflections took 10 ms to scan 1 urls, producing 2 keys and 8 values 19:27:40.268 [main] INFO o.r.Reflections - [scan,232] - Reflections took 9 ms to scan 14 urls, producing 0 keys and 0 values 19:27:40.269 [main] INFO c.a.n.c.r.client - [printIfInfoEnabled,60] - [10025a0f-383b-4399-95f8-7c31d45f15a5_config-0] RpcClient init label, labels = {module=config, Vipserver-Tag=null, source=sdk, Amory-Tag=null, Location-Tag=null, taskId=0, AppName=unknown} 19:27:40.269 [main] INFO c.a.n.c.r.client - [printIfInfoEnabled,60] - [10025a0f-383b-4399-95f8-7c31d45f15a5_config-0] Register server push request handler:com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient$$Lambda$382/1412656257 19:27:40.270 [main] INFO c.a.n.c.r.client - [printIfInfoEnabled,60] - [10025a0f-383b-4399-95f8-7c31d45f15a5_config-0] Register server push request handler:com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient$$Lambda$383/358019805 19:27:40.270 [main] INFO c.a.n.c.r.client - [printIfInfoEnabled,60] - [10025a0f-383b-4399-95f8-7c31d45f15a5_config-0] Registry connection listener to current client:com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient$1 19:27:40.270 [main] INFO c.a.n.c.r.client - [printIfInfoEnabled,60] - [10025a0f-383b-4399-95f8-7c31d45f15a5_config-0] RpcClient init, ServerListFactory = com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient$2 19:27:40.276 [main] INFO c.a.n.c.r.client - [printIfInfoEnabled,60] - [10025a0f-383b-4399-95f8-7c31d45f15a5_config-0] Try to connect to server on start up, server: {serverIp = '124.133.23.84', server main port = 18848} 19:27:40.789 [main] INFO c.a.n.c.r.client - [printIfInfoEnabled,60] - [10025a0f-383b-4399-95f8-7c31d45f15a5_config-0] Success to connect to server [124.133.23.84:18848] on start up, connectionId = 1751282860784_192.168.1.189_55988 19:27:40.790 [com.alibaba.nacos.client.remote.worker] INFO c.a.n.c.r.client - [printIfInfoEnabled,60] - [10025a0f-383b-4399-95f8-7c31d45f15a5_config-0] Notify connected event to listeners. 19:27:40.790 [main] INFO c.a.n.c.r.client - [printIfInfoEnabled,60] - [10025a0f-383b-4399-95f8-7c31d45f15a5_config-0] Register server push request handler:com.alibaba.nacos.common.remote.client.RpcClient$ConnectResetRequestHandler 19:27:40.791 [main] INFO c.a.n.c.r.client - [printIfInfoEnabled,60] - [10025a0f-383b-4399-95f8-7c31d45f15a5_config-0] Register server push request handler:com.alibaba.nacos.common.remote.client.RpcClient$$Lambda$391/193625667 19:27:40.818 [main] ERROR c.a.c.n.c.NacosPropertySourceBuilder - [loadNacosData,101] - get data from Nacos error,dataId:application-dev.yml com.alibaba.nacos.api.exception.NacosException: http error, code=403,msg=authorization failed!,dataId=application-dev.yml,group=DEFAULT_GROUP,tenant=lichao at com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient.queryConfig(ClientWorker.java:979) at com.alibaba.nacos.client.config.impl.ClientWorker.getServerConfig(ClientWorker.java:397) at com.alibaba.nacos.client.config.NacosConfigService.getConfigInner(NacosConfigService.java:166) at com.alibaba.nacos.client.config.NacosConfigService.getConfig(NacosConfigService.java:94) at com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder.loadNacosData(NacosPropertySourceBuilder.java:85) at com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder.build(NacosPropertySourceBuilder.java:73) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadNacosPropertySource(NacosPropertySourceLocator.java:199) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadNacosDataIfPresent(NacosPropertySourceLocator.java:186) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadNacosConfiguration(NacosPropertySourceLocator.java:158) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadSharedConfiguration(NacosPropertySourceLocator.java:116) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.locate(NacosPropertySourceLocator.java:101) at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:51) at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:47) at org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration.initialize(PropertySourceBootstrapConfiguration.java:95) at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:613) at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:381) at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) at com.ruoyi.customApi.OuchnCustomApiApplication.main(OuchnCustomApiApplication.java:33) 19:27:40.823 [main] ERROR c.a.c.n.c.NacosPropertySourceBuilder - [loadNacosData,101] - get data from Nacos error,dataId:ecust-custom-api com.alibaba.nacos.api.exception.NacosException: http error, code=403,msg=authorization failed!,dataId=ecust-custom-api,group=DEFAULT_GROUP,tenant=lichao at com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient.queryConfig(ClientWorker.java:979) at com.alibaba.nacos.client.config.impl.ClientWorker.getServerConfig(ClientWorker.java:397) at com.alibaba.nacos.client.config.NacosConfigService.getConfigInner(NacosConfigService.java:166) at com.alibaba.nacos.client.config.NacosConfigService.getConfig(NacosConfigService.java:94) at com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder.loadNacosData(NacosPropertySourceBuilder.java:85) at com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder.build(NacosPropertySourceBuilder.java:73) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadNacosPropertySource(NacosPropertySourceLocator.java:199) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadNacosDataIfPresent(NacosPropertySourceLocator.java:186) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadApplicationConfiguration(NacosPropertySourceLocator.java:141) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.locate(NacosPropertySourceLocator.java:103) at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:51) at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:47) at org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration.initialize(PropertySourceBootstrapConfiguration.java:95) at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:613) at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:381) at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) at com.ruoyi.customApi.OuchnCustomApiApplication.main(OuchnCustomApiApplication.java:33) 19:27:40.826 [main] ERROR c.a.c.n.c.NacosPropertySourceBuilder - [loadNacosData,101] - get data from Nacos error,dataId:ecust-custom-api.yml com.alibaba.nacos.api.exception.NacosException: http error, code=403,msg=authorization failed!,dataId=ecust-custom-api.yml,group=DEFAULT_GROUP,tenant=lichao at com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient.queryConfig(ClientWorker.java:979) at com.alibaba.nacos.client.config.impl.ClientWorker.getServerConfig(ClientWorker.java:397) at com.alibaba.nacos.client.config.NacosConfigService.getConfigInner(NacosConfigService.java:166) at com.alibaba.nacos.client.config.NacosConfigService.getConfig(NacosConfigService.java:94) at com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder.loadNacosData(NacosPropertySourceBuilder.java:85) at com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder.build(NacosPropertySourceBuilder.java:73) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadNacosPropertySource(NacosPropertySourceLocator.java:199) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadNacosDataIfPresent(NacosPropertySourceLocator.java:186) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadApplicationConfiguration(NacosPropertySourceLocator.java:144) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.locate(NacosPropertySourceLocator.java:103) at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:51) at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:47) at org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration.initialize(PropertySourceBootstrapConfiguration.java:95) at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:613) at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:381) at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) at com.ruoyi.customApi.OuchnCustomApiApplication.main(OuchnCustomApiApplication.java:33) 19:27:40.830 [main] ERROR c.a.c.n.c.NacosPropertySourceBuilder - [loadNacosData,101] - get data from Nacos error,dataId:ecust-custom-api-dev.yml com.alibaba.nacos.api.exception.NacosException: http error, code=403,msg=authorization failed!,dataId=ecust-custom-api-dev.yml,group=DEFAULT_GROUP,tenant=lichao at com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient.queryConfig(ClientWorker.java:979) at com.alibaba.nacos.client.config.impl.ClientWorker.getServerConfig(ClientWorker.java:397) at com.alibaba.nacos.client.config.NacosConfigService.getConfigInner(NacosConfigService.java:166) at com.alibaba.nacos.client.config.NacosConfigService.getConfig(NacosConfigService.java:94) at com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder.loadNacosData(NacosPropertySourceBuilder.java:85) at com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder.build(NacosPropertySourceBuilder.java:73) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadNacosPropertySource(NacosPropertySourceLocator.java:199) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadNacosDataIfPresent(NacosPropertySourceLocator.java:186) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.loadApplicationConfiguration(NacosPropertySourceLocator.java:149) at com.alibaba.cloud.nacos.client.NacosPropertySourceLocator.locate(NacosPropertySourceLocator.java:103) at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:51) at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:47) at org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration.initialize(PropertySourceBootstrapConfiguration.java:95) at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:613) at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:381) at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) at com.ruoyi.customApi.OuchnCustomApiApplication.main(OuchnCustomApiApplication.java:33) 19:27:40.833 [main] INFO c.r.c.OuchnCustomApiApplication - [logStartupProfileInfo,646] - The following 1 profile is active: "dev" 19:27:42.183 [main] INFO c.u.j.c.EnableEncryptablePropertiesBeanFactoryPostProcessor - [postProcessBeanFactory,40] - Post-processing PropertySource instances 19:27:42.183 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource bootstrapProperties-ecust-custom-api-dev.yml,DEFAULT_GROUP [org.springframework.cloud.bootstrap.config.BootstrapPropertySource] to EncryptableEnumerablePropertySourceWrapper 19:27:42.184 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource bootstrapProperties-ecust-custom-api.yml,DEFAULT_GROUP [org.springframework.cloud.bootstrap.config.BootstrapPropertySource] to EncryptableEnumerablePropertySourceWrapper 19:27:42.184 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource bootstrapProperties-ecust-custom-api,DEFAULT_GROUP [org.springframework.cloud.bootstrap.config.BootstrapPropertySource] to EncryptableEnumerablePropertySourceWrapper 19:27:42.184 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource bootstrapProperties-application-dev.yml,DEFAULT_GROUP [org.springframework.cloud.bootstrap.config.BootstrapPropertySource] to EncryptableEnumerablePropertySourceWrapper 19:27:42.184 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,76] - Skipping PropertySource configurationProperties [class org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertySource 19:27:42.184 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,76] - Skipping PropertySource servletConfigInitParams [class org.springframework.core.env.PropertySource$StubPropertySource 19:27:42.184 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,76] - Skipping PropertySource servletContextInitParams [class org.springframework.core.env.PropertySource$StubPropertySource 19:27:42.184 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource systemProperties [org.springframework.core.env.PropertiesPropertySource] to EncryptableMapPropertySourceWrapper 19:27:42.184 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource systemEnvironment [org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource] to EncryptableSystemEnvironmentPropertySourceWrapper 19:27:42.184 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource random [org.springframework.boot.env.RandomValuePropertySource] to EncryptablePropertySourceWrapper 19:27:42.184 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource cachedrandom [org.springframework.cloud.util.random.CachedRandomPropertySource] to EncryptablePropertySourceWrapper 19:27:42.184 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource springCloudClientHostInfo [org.springframework.core.env.MapPropertySource] to EncryptableMapPropertySourceWrapper 19:27:42.184 [main] INFO c.u.j.EncryptablePropertySourceConverter - [makeEncryptable,81] - Converting PropertySource springCloudDefaultProperties [org.springframework.core.env.MapPropertySource] to EncryptableMapPropertySourceWrapper 19:27:42.263 [main] INFO i.s.s.b.a.SeataAutoConfiguration - [globalTransactionScanner,65] - Automatically configure Seata 19:27:42.263 [main] INFO c.u.j.f.DefaultLazyPropertyFilter - [lambda$new$2,31] - Property Filter custom Bean not found with name 'encryptablePropertyFilter'. Initializing Default Property Filter 19:27:42.268 [main] INFO c.u.j.r.DefaultLazyPropertyResolver - [lambda$new$2,35] - Property Resolver custom Bean not found with name 'encryptablePropertyResolver'. Initializing Default Property Resolver 19:27:42.268 [main] INFO c.u.j.d.DefaultLazyPropertyDetector - [lambda$new$2,35] - Property Detector custom Bean not found with name 'encryptablePropertyDetector'. Initializing Default Property Detector 19:27:42.299 [main] INFO i.s.c.ConfigurationFactory - [<clinit>,65] - load Configuration:FileConfiguration$$EnhancerByCGLIB$$862af1eb 19:27:42.306 [main] INFO i.s.c.ConfigurationFactory - [buildConfiguration,123] - load Configuration:FileConfiguration$$EnhancerByCGLIB$$862af1eb 19:27:42.337 [main] INFO i.s.s.a.GlobalTransactionScanner - [initClient,164] - Initializing Global Transaction Clients ... 19:27:42.372 [main] INFO i.s.c.r.n.NettyClientBootstrap - [start,147] - NettyClientBootstrap has started 19:27:42.372 [main] INFO i.s.s.a.GlobalTransactionScanner - [initClient,172] - Transaction Manager Client is initialized. applicationId[ecust-custom-api-li] txServiceGroup[ecust-custom-api-li-seata-service-group] 19:27:42.378 [main] INFO i.s.r.d.AsyncWorker - [init,125] - Async Commit Buffer Limit: 10000 19:27:42.378 [main] INFO i.s.r.d.x.ResourceManagerXA - [init,40] - ResourceManagerXA init ... 19:27:42.382 [main] INFO i.s.c.r.n.NettyClientBootstrap - [start,147] - NettyClientBootstrap has started 19:27:42.382 [main] INFO i.s.s.a.GlobalTransactionScanner - [initClient,177] - Resource Manager is initialized. applicationId[ecust-custom-api-li] txServiceGroup[ecust-custom-api-li-seata-service-group] 19:27:42.382 [main] INFO i.s.s.a.GlobalTransactionScanner - [initClient,181] - Global Transaction Clients are initialized. 19:27:42.900 [main] INFO o.a.c.c.AprLifecycleListener - [log,173] - Loaded Apache Tomcat Native library [1.3.1] using APR version [1.7.4]. 19:27:42.900 [main] INFO o.a.c.c.AprLifecycleListener - [log,173] - APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [true]. 19:27:42.900 [main] INFO o.a.c.c.AprLifecycleListener - [log,173] - APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true] 19:27:42.904 [main] INFO o.a.c.c.AprLifecycleListener - [log,173] - OpenSSL successfully initialized [OpenSSL 3.0.14 4 Jun 2024] 19:27:42.912 [main] INFO o.a.c.h.Http11NioProtocol - [log,173] - Initializing ProtocolHandler ["http-nio-9205"] 19:27:42.913 [main] INFO o.a.c.c.StandardService - [log,173] - Starting service [Tomcat] 19:27:42.913 [main] INFO o.a.c.c.StandardEngine - [log,173] - Starting Servlet engine: [Apache Tomcat/9.0.60] 19:27:42.992 [main] INFO o.a.c.c.C.[.[.[/] - [log,173] - Initializing Spring embedded WebApplicationContext 19:27:43.146 [main] WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - [refresh,591] - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redissonConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.redis.host' in value "${spring.redis.host}" 19:27:43.149 [main] INFO o.a.c.c.StandardService - [log,173] - Stopping service [Tomcat] 19:27:43.185 [main] ERROR o.s.b.SpringApplication - [reportFailure,830] - Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redissonConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.redis.host' in value "${spring.redis.host}" at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:405) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) at com.ruoyi.customApi.OuchnCustomApiApplication.main(OuchnCustomApiApplication.java:33) Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.redis.host' in value "${spring.redis.host}" at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:180) at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126) at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239) at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210) at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:191) at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:936) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1330) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1309) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ... 17 common frames omitted 19:27:43.186 [Thread-4] WARN c.a.n.c.h.HttpClientBeanHolder - [shutdown,108] - [HttpClientBeanHolder] Start destroying common HttpClient 19:27:43.186 [Thread-11] WARN c.a.n.c.n.NotifyCenter - [shutdown,136] - [NotifyCenter] Start destroying Publisher 19:27:43.186 [Thread-11] WARN c.a.n.c.n.NotifyCenter - [shutdown,153] - [NotifyCenter] Destruction of the end 19:27:43.186 [Thread-4] WARN c.a.n.c.h.HttpClientBeanHolder - [shutdown,114] - [HttpClientBeanHolder] Destruction of the end
最新发布
07-01
<think>我们分析日志和问题描述,用户启动SpringBoot应用时遇到两个主要错误: 1. Nacos配置获取失败,出现403授权错误(Authorization failed) 2.无法解析占位符'spring.redis.host',导致RedissonConfigbean创建失败结合引用内容,我们给出以下解决方案: ###一、解决Nacos403授权失败问题####原因分析日志显示:```log19:24:26.336[main] ERRORc.a.c.n.c.NacosPropertySourceBuilder -[loadNacosData,101]- getdata fromNacoserror,dataId:application-dev.ymlcom.alibaba.nacos.api.exception.NacosException:http error, code=403,msg=authorization failed!,dataId=application-dev.yml,group=DEFAULT_GROUP,tenant=lichao```这表明应用在尝试从Nacos获取配置时,由于权限不足被拒绝(403错误)。通常是因为Nacos服务端开启了认证,而客户端未提供正确的用户名和密码。####解决方案1.**在bootstrap.yml中添加Nacos认证信息**根据引用[1]和引用[3],配置中心需要bootstrap.yml(或bootstrap.properties)来优先加载配置。添加以下配置:```yamlspring:cloud:nacos:config:username:${NACOS_USERNAME:nacos}#默认用户名,可通过环境变量覆盖password: ${NACOS_PASSWORD:nacos}#默认密码server-addr:124.133.23.84:18848#根据日志中的地址填写discovery:server-addr: ${spring.cloud.nacos.config.server-addr}```>**注意**:>-如果Nacos服务端使用非默认账号,请替换`username`和`password`> -如果配置了命名空间(tenant),请添加`namespace: your-namespace-id`[^1][^3] 2. **检查Nacos服务端权限设置**登录Nacos控制台(`http://124.133.23.84:18848/nacos`):-确认账号`lichao`(日志中的tenant)是否存在-检查该账号是否有读取`application-dev.yml`等配置的权限###二、解决Redis配置缺失问题####原因分析日志显示:```logCaused by: java.lang.IllegalArgumentException:Could notresolve placeholder'spring.redis.host' invalue "${spring.redis.host}"``` 这表明应用在解析Redis配置时失败,因为配置源中不存在`spring.redis.host`。可能原因: 1. Redis配置未在Nacos中正确设置2.因Nacos授权失败导致Redis配置未被加载####解决方案1.**在Nacos中添加Redis配置**确保Nacos中存在以下配置(以`ecust-custom-api.yml`为例):```yamlspring:redis:host: your-redis-host# Redis服务器地址port:6379#默认端口password:your-password#如果有密码database:0#默认DB```> **注意**:如果密码已加密(如使用Jasypt),需确保格式为`ENC(加密字符串)`,并配置解密密钥。2.**验证配置加载**在解决Nacos403问题后,检查应用启动日志是否出现:```logLoaded configfile 'ecust-custom-api.yml' fromNacos```###三、完整配置示例#### bootstrap.yml```yamlspring:application:name:ecust-custom-apicloud:nacos:config:username: nacos_prod_userpassword:secure_password_hereserver-addr:124.133.23.84:18848namespace: lichao#与日志中的tenant一致file-extension: ymldiscovery:server-addr: ${spring.cloud.nacos.config.server-addr} ```#### Nacos中的ecust-custom-api.yml```yamlspring:redis:host:192.168.10.100#实际Redis地址password: ENC(AbCdEfG123456)#加密后的密码database:1#其他应用配置...``` ###四、启动命令建议如果通过环境变量传递敏感信息:```bashjava-jaryour-app.jar\--spring.cloud.nacos.config.username=${NACOS_USER} \--spring.cloud.nacos.config.password=${NACOS_PWD} \--jasypt.encryptor.password=${JASYPT_KEY}#如果配置了加密``` >**关键点总结**:>1. Nacos403错误必须通过添加账号密码解决>2. Redis配置缺失根源在于Nacos配置未加载成功>3.确保bootstrap.yml优先加载配置[^3]§§相关问题§§1.如何在SpringBoot中正确使用bootstrap.yml?2. Nacos权限控制的最佳实践有哪些?3.如何用Jasypt加密Nacos中的敏感配置?</think>根据日志分析,您的 Spring Boot 应用启动失败涉及两个核心问题:Nacos 403 授权失败和 Redis 配置缺失。以下是系统化的解决方案: ### 一、解决 Nacos 403 授权失败问题 #### 原因分析 日志显示多个配置获取失败: ```log 19:24:26.336 [main] ERROR c.a.c.n.c.NacosPropertySourceBuilder - get data from Nacos error... com.alibaba.nacos.api.exception.NacosException: http error, code=403,msg=authorization failed! ``` 这表明 Nacos 服务端拒绝了配置访问请求,通常是因为: 1. 未配置认证信息 2. 使用的账号无权限访问配置 3. 命名空间(tenant)配置错误 #### 解决方案 1. **添加 Nacos 认证配置** 在 `bootstrap.yml` 中添加用户名和密码(根据引用[1]和引用[3]): ```yaml spring: cloud: nacos: config: username: ${NACOS_USER:nacos} # 默认用户名 password: ${NACOS_PWD:nacos} # 默认密码 server-addr: 124.133.23.84:18848 # 日志中的地址 namespace: lichao # 日志中的tenant值 ``` 2. **检查 Nacos 服务端权限** - 登录 Nacos 控制台 (`http://124.133.23.84:18848/nacos`) - 在 **权限控制 > 用户管理** 确认账号状态 - 在 **配置管理** 检查 `application-dev.yml` 等文件的读取权限 3. **验证命名空间配置** - 在 Nacos 控制台确认 `lichao` 命名空间是否存在 - 如果使用公共命名空间,可移除配置: ```yaml spring.cloud.nacos.config.namespace: public ``` ### 二、解决 Redis 配置缺失问题 #### 原因分析 日志显示: ```log Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.redis.host' in value "${spring.redis.host}" ``` 这表明 Redis 配置未正确加载,通常因为: 1. Redis 配置未在 Nacos 中设置 2. 因 Nacos 授权失败导致配置未加载 #### 解决方案 1. **在 Nacos 中添加 Redis 配置** 在 `ecust-custom-api.yml` 中添加: ```yaml spring: redis: host: ${REDIS_HOST:localhost} port: ${REDIS_PORT:6379} password: ${REDIS_PWD:} database: 0 ``` 2. **优先解决 Nacos 访问问题** 由于 Redis 配置依赖 Nacos,必须先解决 Nacos 403 错误,确保配置能正常加载 ### 三、完整配置示例 #### bootstrap.yml ```yaml spring: application: name: ecust-custom-api cloud: nacos: config: username: nacos_user password: nacos_password server-addr: 124.133.23.84:18848 namespace: lichao file-extension: yaml discovery: server-addr: ${spring.cloud.nacos.config.server-addr} ``` #### Nacos 中的 ecust-custom-api.yml ```yaml spring: redis: host: 192.168.10.100 port: 6379 password: ENC(加密密码) # 如果使用加密 database: 1 # 其他应用配置... ``` ### 四、启动验证 1. 先确保 Nacos 服务可访问且账号正确 2. 启动应用时观察日志: - 检查 `Success to connect to server` 提示 - 确认无 `authorization failed` 错误 - 验证 Redis 连接初始化成功 > **关键点**:Nacos 配置中心的访问必须在应用启动前完成(通过 bootstrap.yml),这是 Spring Cloud 的加载机制决定的[^3]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值