其他分享
首页 > 其他分享> > nacos优先使用本地配置文件

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