nacos优先使用本地配置文件
作者:互联网
最近项目组在进行nacos 的项目改造,个人也开始学习了一些关于nacos 的东西,在使用时个人想要使用本地文件,然后网上查询了一些办法,如在nacos 远端对应的微服务配置文件中加上:
如果本地配置优先级高,那么 override-none 设置为 true,包括系统环境变量、本地配置文件等配置 spring.cloud.config.override-none=true 如果想要远程配置优先级高,那么 allow-override 设置为 false,如果想要本地配置优先级高那么 allow-override 设置为 true spring.cloud.config.allow-override=true 只有系统环境变量或者系统属性才能覆盖远程配置文件的配置,本地配置文件中配置优先级低于远程配置;注意本地配置文件不是系统属性 spring.cloud.config.override-system-properties=false
这三个配置,然后本地启动的时候仍然还是拉取了最新的配置在,本机的目录:
C:\Users\XXXX\nacos\config\fixed-XXXX.XXXX.XXXX.com-XXXX-loc_nacos\snapshot-tenant\XXXX-loc\loc
下的文件 "XXXX-service.properties" 还是被强制刷新了,这个时候我就很费解,为啥不生效呢,然后在网上查呀查,最后发现在本地debug时使用类"LocalConfigInfoProcessor" 下的 "getFailover()" 方法时在如下代码的变量
"localPath" 获取到的路径变量(C:\Users\XXXX\nacos\config\fixed-XXXX.XXXX.XXXX.com-XXXX-loc_nacos\data\config-data-tenant\XXXX-loc\loc\)我本机压根就没有
然后我按照debug 的变量将对应的数据放置到了本机,然后重新开始debug,此时根据启动日志发现已经开始优先读取本地文件了。
通过阅读源码个人也知道了路径是如何组成的,首先先看看类"LocalConfigInfoProcessor" 下的私有方法"getFailover":
static public String getFailover(String serverName, String dataId, String group, String tenant) { File localPath = getFailoverFile(serverName, dataId, group, tenant); if (!localPath.exists() || !localPath.isFile()) { return null; } try { return readFile(localPath); } catch (IOException ioe) { LOGGER.error("[" + serverName + "] get failover error, " + localPath, ioe); return null; } }
其中 "getFailoverFile" 方法就是负责组装路径的详细代码如下:
static File getFailoverFile(String serverName, String dataId, String group, String tenant) { File tmp = new File(LOCAL_SNAPSHOT_PATH, serverName + "_nacos"); tmp = new File(tmp, "data"); if (StringUtils.isBlank(tenant)) { tmp = new File(tmp, "config-data"); } else { tmp = new File(tmp, "config-data-tenant"); tmp = new File(tmp, tenant); } return new File(new File(tmp, group), dataId); }
组装完成后其大概格式为:"user.home/nacos/config/serverName_nacos/data/config-data-tenant/tenant/group/dataId" 其中"LOCAL_SNAPSHOT_PATH" 为:
LOCAL_SNAPSHOT_PATH = System.getProperty("JM.SNAPSHOT.PATH", System.getProperty("user.home")) + File.separator + "nacos" + File.separator + "config";
即"user.home/nacos/config",
剩下的serverName 属性是在类"ServerListManager" 下通过方法"ServerListManager" 方法进行了重新拼接的
public ServerListManager(Properties properties) throws NacosException { isStarted = false; serverAddrsStr = properties.getProperty(PropertyKeyConst.SERVER_ADDR); String namespace = properties.getProperty(PropertyKeyConst.NAMESPACE); initParam(properties); if (StringUtils.isNotEmpty(serverAddrsStr)) { isFixed = true; List<String> serverAddrs = new ArrayList<String>(); String[] serverAddrsArr = serverAddrsStr.split(","); for (String serverAddr: serverAddrsArr) { if (serverAddr.startsWith(HTTPS) || serverAddr.startsWith(HTTP)) { serverAddrs.add(serverAddr); } else { String[] serverAddrArr = serverAddr.split(":"); if (serverAddrArr.length == 1) { serverAddrs.add(HTTP + serverAddrArr[0] + ":" + ParamUtil.getDefaultServerPort()); } else { serverAddrs.add(HTTP + serverAddr); } } } serverUrls = serverAddrs; if (StringUtils.isBlank(namespace)) { name = FIXED_NAME + "-" + getFixedNameSuffix(serverUrls.toArray(new String[serverUrls.size()])); } else { this.namespace = namespace; this.tenant = namespace; name = FIXED_NAME + "-" + getFixedNameSuffix(serverUrls.toArray(new String[serverUrls.size()])) + "-" + namespace; } } else { if (StringUtils.isBlank(endpoint)) { throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "endpoint is blank"); } isFixed = false; if (StringUtils.isBlank(namespace)) { name = endpoint; addressServerUrl = String.format("http://%s:%d/%s/%s", endpoint, endpointPort, contentPath, serverListName); } else { this.namespace = namespace; this.tenant = namespace; name = endpoint + "-" + namespace; addressServerUrl = String.format("http://%s:%d/%s/%s?namespace=%s", endpoint, endpointPort, contentPath, serverListName, namespace); } } }
其中需要重点看 serverName 属性基本上是这样子的
name = FIXED_NAME + "-" + getFixedNameSuffix(serverUrls.toArray(new String[serverUrls.size()])) + "-" + namespace;
这段代码,最后的结果为"fixed-XXXX.XXXX.XXXX.com-XXXX-loc"基本组成格式是"fixed-" +
spring.cloud.nacos.config.server-addr 内属性的值 +"-"+ spring.cloud.nacos.config.namespace 内属性的值
如我这里的properties 的属性值为
spring.cloud.nacos.config.namespace=XXXX-loc spring.cloud.nacos.config.server-addr=http://XXXX.XXXX.XXXX.com spring.cloud.nacos.config.group=loc spring.cloud.nacos.config.name=XXXX-XXXX-service spring.cloud.nacos.config.file-extension=properties
最后组装的结果就成了"fixed-XXXX.XXXX.XXXX.com-XXXX-loc" 最后在
static File getFailoverFile(String serverName, String dataId, String group, String tenant) { //这个方法的第一句中加上了"_nacos" 后缀也就成了 "fixed-XXXX.XXXX.XXXX.com-XXXX-loc_nacos" 这个路径值 File tmp = new File(LOCAL_SNAPSHOT_PATH, serverName + "_nacos"); // 在加上你后缀 data 就成了路径“C:\Users\XXXX\nacos\config\fixed-XXXX.XXXX.XXXX.com-XXXX-loc_nacos\data” tmp = new File(tmp, "data"); // 假如 tenant 不为"" 就在路径上加上"config-data" 随后变成 C:\Users\XXXX\nacos\config\fixed-XXXX.XXXX.XXXX.com-XXXX-loc_nacos\data\config-data-tenant\XXXX-loc\ if (StringUtils.isBlank(tenant)) { tmp = new File(tmp, "config-data"); } else { tmp = new File(tmp, "config-data-tenant"); tmp = new File(tmp, tenant); } // 最后加上group 和 dataId 路径就成了 C:\Users\XXXX\nacos\config\fixed-XXXX.XXXX.XXXX.com-XXXX-loc_nacos\data\config-data-tenant\XXXX-loc\loc\XXXX-XXXX-service return new File(new File(tmp, group), dataId); }
这里有意思的是"getFailover" 方法被调用了两次导致这个方法的返回值一次是:
"C:\Users\XXXX\nacos\config\fixed-XXXX.XXXX.XXXX.com-XXXX-loc_nacos\data\config-data-tenant\XXXX-loc\loc\XXXX-XXXX-service" 一次是:
"C:\Users\XXXX\nacos\config\fixed-XXXX.XXXX.XXXX.com-XXXX-loc_nacos\data\config-data-tenant\XXXX-loc\loc\XXXX-XXXX-service.properties"
。 这又引起了我的兴趣,然后继续跟源码,跟踪到
类"NacosPropertySourceLocator" 下的私有方法"loadApplicationConfiguration"
private void loadApplicationConfiguration( CompositePropertySource compositePropertySource, String dataIdPrefix, NacosConfigProperties properties, Environment environment) { String fileExtension = properties.getFileExtension(); String nacosGroup = properties.getGroup(); // load directly once by default loadNacosDataIfPresent(compositePropertySource, dataIdPrefix, nacosGroup, fileExtension, true); // load with suffix, which have a higher priority than the default loadNacosDataIfPresent(compositePropertySource, dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true); // Loaded with profile, which have a higher priority than the suffix for (String profile : environment.getActiveProfiles()) { String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension; loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup, fileExtension, true); } }
其中 loadNacosDataIfPresent 这个方法调用了两次,且每次入参还都不是很一样重点表现在第二个参数的组成不一样,一个是dataIdPrefix,另一个是 "dataIdPrefix + "." + fileExtension",则入参结果也是一个为"XXXX-XXXX-service" 另一个为"XXXX-XXXX-service.properties" .
假如想要看最终读取配置文件结果的话需要进入到类 "NacosConfigService" 中查看 "getConfigInner" 方法
private String getConfigInner(String tenant, String dataId, String group, long timeoutMs) throws NacosException { group = null2defaultGroup(group); ParamUtils.checkKeyParam(dataId, group); ConfigResponse cr = new ConfigResponse(); cr.setDataId(dataId); cr.setTenant(tenant); cr.setGroup(group); // 优先使用本地配置 String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant); if (content != null) { LOGGER.warn("[{}] [get-config] get failover ok, dataId={}, group={}, tenant={}, config={}", agent.getName(), dataId, group, tenant, ContentUtils.truncateContent(content)); cr.setContent(content); configFilterChainManager.doFilter(null, cr); content = cr.getContent(); return content; } try { String[] ct = worker.getServerConfig(dataId, group, tenant, timeoutMs); cr.setContent(ct[0]); configFilterChainManager.doFilter(null, cr); content = cr.getContent(); return content; } catch (NacosException ioe) { if (NacosException.NO_RIGHT == ioe.getErrCode()) { throw ioe; } LOGGER.warn("[{}] [get-config] get from server error, dataId={}, group={}, tenant={}, msg={}", agent.getName(), dataId, group, tenant, ioe.toString()); } LOGGER.warn("[{}] [get-config] get snapshot ok, dataId={}, group={}, tenant={}, config={}", agent.getName(), dataId, group, tenant, ContentUtils.truncateContent(content)); content = LocalConfigInfoProcessor.getSnapshot(agent.getName(), dataId, group, tenant); cr.setContent(content); configFilterChainManager.doFilter(null, cr); content = cr.getContent(); return content; }
主要需要把断点打到 " String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant); " 这一行上 ,如图:
写到这里我也就清楚了整个事件的原委了。打完,收工~
标签:优先,XXXX,String,配置文件,nacos,group,config,tenant 来源: https://www.cnblogs.com/Solomon-Kane-zm/p/16365268.html