前言

最近搭建 xxx服务 的时候碰到了一个这样的问题 

xxx服务需要一系列的配置, 然后我直接在 nacos 数据库中增加了给定的名称空间, 以及增加了对应的一系列的 配置信息, 但是 当我应用这边配置好了相关配置之后, 应用这边确获取不到相应的配置 

之前 记录了一个 todo, 今天 来梳理一下 

主要是会涉及到我们关注的问题, 以及 nacos配置查询的流程 

客户端 获取 nacos 配置

客户端获取 nacos 配置, 处理堆栈信息如下 

请求的 url 为 "http://10.60.50.16:8849/nacos/v1/cs/configs

传入了 dataId, group, tenant 三个参数, 来唯一确定一个 config 

getServerConfig:230, ClientWorker (com.alibaba.nacos.client.config.impl)
getConfigInner:143, NacosConfigService (com.alibaba.nacos.client.config)
getConfig:92, NacosConfigService (com.alibaba.nacos.client.config)
loadNacosData:85, NacosPropertySourceBuilder (org.springframework.cloud.alibaba.nacos.client)
build:75, NacosPropertySourceBuilder (org.springframework.cloud.alibaba.nacos.client)
loadNacosDataIfPresent:179, NacosPropertySourceLocator (org.springframework.cloud.alibaba.nacos.client)
loadSharedConfiguration:111, NacosPropertySourceLocator (org.springframework.cloud.alibaba.nacos.client)
locate:86, NacosPropertySourceLocator (org.springframework.cloud.alibaba.nacos.client)
initialize:97, PropertySourceBootstrapConfiguration (org.springframework.cloud.bootstrap.config)
applyInitializers:649, SpringApplication (org.springframework.boot)
prepareContext:373, SpringApplication (org.springframework.boot)
run:314, SpringApplication (org.springframework.boot)
run:1260, SpringApplication (org.springframework.boot)
run:1248, SpringApplication (org.springframework.boot)

nacos 处理获取配置请求 

nacos 处理获取配置请求, 处理堆栈信息如下 

在 standalone 模式下面, 是直接获取的 dump 在本地的 config 的文件信息 

public 的 tenant 和 其他的 tenant 根路径不一样, 分别是在 "~/nacos/data/config-data " 和 "~/nacos/data/tenant-config-data" 

获取到 config 的内容之后, 直接响应给 客户端 

doGetConfig:188, ConfigServletInner (com.alibaba.nacos.config.server.controller)
getConfig:210, ConfigController (com.alibaba.nacos.config.server.controller)

客户端拿到 nacos 的响应之后的处理 

客户端这边的处理是在 ClientWorker.getCache(String dataId, String group, String tenant) 

如果 nacos 响应 200, 拿到响应, 返回 {content, contentType}

如果 nacos 响应 404, 返回 {null, null} 

对于拿到配置的情况, 获取对应的配置并加载[properties 或者 yaml], 对于 没有拿到配置的情况, 响应一个 EMPTY_PROPERTIES 

        switch(result.code) {
        case 200:
            LocalConfigInfoProcessor.saveSnapshot(this.agent.getName(), dataId, group, tenant, result.content);
            ct[0] = result.content;
            if (result.headers.containsKey("Config-Type")) {
                ct[1] = (String)((List)result.headers.get("Config-Type")).get(0);
            } else {
                ct[1] = ConfigType.TEXT.getType();
            }

            return ct;
        case 403:
            LOGGER.error("[{}] [sub-server-error] no right, dataId={}, group={}, tenant={}", new Object[]{this.agent.getName(), dataId, group, tenant});
            throw new NacosException(result.code, result.content);
        case 404:
            LocalConfigInfoProcessor.saveSnapshot(this.agent.getName(), dataId, group, tenant, (String)null);
            return ct;
        case 409:
            LOGGER.error("[{}] [sub-server-error] get server config being modified concurrently, dataId={}, group={}, tenant={}", new Object[]{this.agent.getName(), dataId, group, tenant});
            throw new NacosException(409, "data being modified, dataId=" + dataId + ",group=" + group + ",tenant=" + tenant);
        default:
            LOGGER.error("[{}] [sub-server-error]  dataId={}, group={}, tenant={}, code={}", new Object[]{this.agent.getName(), dataId, group, tenant, result.code});
            throw new NacosException(result.code, "http error, code=" + result.code + ",dataId=" + dataId + ",group=" + group + ",tenant=" + tenant);
        }

nacos 初始化的时候持久化 config 的处理

处理对应的堆栈信息如下 

ConfigCacheService.dump(String dataId, String group, String tenant, String content, long lastModifiedTs, String type) 中 makeSure 来创建 当前配置 对应的 CacheItem 其中包含了上面获取配置需要的 $configFile+$group+$namespaceId 的读写锁 

standalone 模式下面, 还需要将 config 持久化到磁盘, 上面 "nacos 处理获取配置请求" 来读取给定的配置持久化的文件 

DumpAllProcessor.process(NacosTask task) 中遍历了 nacos 中的所有文件, 来持久化配置到磁盘 

dump:114, ConfigCacheService (com.alibaba.nacos.config.server.service)
process:71, DumpAllProcessor (com.alibaba.nacos.config.server.service.dump.processor)
dumpConfigInfo:282, DumpService (com.alibaba.nacos.config.server.service.dump)
dumpOperate:195, DumpService (com.alibaba.nacos.config.server.service.dump)
init:52, ExternalDumpService (com.alibaba.nacos.config.server.service.dump)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:363, InitDestroyAnnotationBeanPostProcessor$LifecycleElement (org.springframework.beans.factory.annotation)
invokeInitMethods:307, InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata (org.springframework.beans.factory.annotation)
postProcessBeforeInitialization:136, InitDestroyAnnotationBeanPostProcessor (org.springframework.beans.factory.annotation)
applyBeanPostProcessorsBeforeInitialization:413, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
initializeBean:1761, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:592, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:514, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:321, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 95369743 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$146)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:319, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:199, AbstractBeanFactory (org.springframework.beans.factory.support)
resolveCandidate:277, DependencyDescriptor (org.springframework.beans.factory.config)
doResolveDependency:1276, DefaultListableBeanFactory (org.springframework.beans.factory.support)
resolveDependency:1196, DefaultListableBeanFactory (org.springframework.beans.factory.support)
resolveAutowiredArgument:857, ConstructorResolver (org.springframework.beans.factory.support)
createArgumentArray:760, ConstructorResolver (org.springframework.beans.factory.support)
autowireConstructor:218, ConstructorResolver (org.springframework.beans.factory.support)
autowireConstructor:1338, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBeanInstance:1185, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:554, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:514, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:321, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 95369743 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$146)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:319, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:199, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:866, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:878, AbstractApplicationContext (org.springframework.context.support)
refresh:550, AbstractApplicationContext (org.springframework.context.support)
refresh:141, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:744, SpringApplication (org.springframework.boot)
refreshContext:391, SpringApplication (org.springframework.boot)
run:312, SpringApplication (org.springframework.boot)
run:1215, SpringApplication (org.springframework.boot)
run:1204, SpringApplication (org.springframework.boot)
main:36, Config (com.alibaba.nacos.config.server)

standalone 模式下, 直接在数据库增加了一份 名称空间 + 配置, 客户端获取不到配置 ?

在获取新增的 xx_import 的名称空间配置的时候 

ConfigServletInner.doGetConfig(HttpServletRequest request, HttpServletResponse response, String dataId, String group, String tenant, String tag, String isNotify, String clientIp) 中 tryConfigReadLock(groupKey) 中尝试获取 $configFile+$group+$namespaceId 的读锁的时候获取失败[即使能够获取到读锁, 对应的 dump 的配置文件也不存在, 还是会响应 404] 

服务端直接 响应 404 给客户端  

然后 客户端接收到 404 之后, 响应了 {null, null} 给 NacosConfigService.getConfigInner 

等价于 客户端获取不到配置 

处理的方式, 重启一下 nacos 就行, 重新全部 dump 一下配置文件到磁盘 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐