聊聊nacos的LocalConfigInfoProcessor

18次阅读

共计 5855 个字符,预计需要花费 15 分钟才能阅读完成。

本文主要研究一下 nacos 的 LocalConfigInfoProcessor

LocalConfigInfoProcessor

nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java

public class LocalConfigInfoProcessor {private static final Logger LOGGER = LogUtils.logger(LocalConfigInfoProcessor.class);

    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;
        }
    }

    /**
     * 获取本地缓存文件内容。NULL 表示没有本地文件或抛出异常。*/
    static public String getSnapshot(String name, String dataId, String group, String tenant) {if (!SnapShotSwitch.getIsSnapShot()) {return null;}
        File file = getSnapshotFile(name, dataId, group, tenant);
        if (!file.exists() || !file.isFile()) {return null;}

        try {return readFile(file);
        } catch (IOException ioe) {LOGGER.error("[" + name + "]+get snapshot error," + file, ioe);
            return null;
        }
    }

    static private String readFile(File file) throws IOException {if (!file.exists() || !file.isFile()) {return null;}

        if (JVMUtil.isMultiInstance()) {return ConcurrentDiskUtil.getFileContent(file, Constants.ENCODE);
        } else {
            InputStream is = null;
            try {is = new FileInputStream(file);
                return IOUtils.toString(is, Constants.ENCODE);
            } finally {
                try {if (null != is) {is.close();
                    }
                } catch (IOException ioe) {}}
        }
    }

    static public void saveSnapshot(String envName, String dataId, String group, String tenant, String config) {if (!SnapShotSwitch.getIsSnapShot()) {return;}
        File file = getSnapshotFile(envName, dataId, group, tenant);
        if (null == config) {
            try {IOUtils.delete(file);
            } catch (IOException ioe) {LOGGER.error("[" + envName + "] delete snapshot error," + file, ioe);
            }
        } else {
            try {File parentFile = file.getParentFile();
                if (!parentFile.exists()) {boolean isMdOk = parentFile.mkdirs();
                    if (!isMdOk) {LOGGER.error("[{}] save snapshot error", envName);
                    }
                }

                if (JVMUtil.isMultiInstance()) {
                    ConcurrentDiskUtil.writeFileContent(file, config,
                        Constants.ENCODE);
                } else {IOUtils.writeStringToFile(file, config, Constants.ENCODE);
                }
            } catch (IOException ioe) {LOGGER.error("[" + envName + "] save snapshot error," + file, ioe);
            }
        }
    }

    /**
     * 清除 snapshot 目录下所有缓存文件。*/
    static public void cleanAllSnapshot() {
        try {File rootFile = new File(LOCAL_SNAPSHOT_PATH);
            File[] files = rootFile.listFiles();
            if (files == null || files.length == 0) {return;}
            for (File file : files) {if (file.getName().endsWith("_nacos")) {IOUtils.cleanDirectory(file);
                }
            }
        } catch (IOException ioe) {LOGGER.error("clean all snapshot error," + ioe.toString(), ioe);
        }
    }

    static public void cleanEnvSnapshot(String envName) {File tmp = new File(LOCAL_SNAPSHOT_PATH, envName + "_nacos");
        tmp = new File(tmp, "snapshot");
        try {IOUtils.cleanDirectory(tmp);
            LOGGER.info("success delete" + envName + "-snapshot");
        } catch (IOException e) {LOGGER.info("fail delete" + envName + "-snapshot," + e.toString());
            e.printStackTrace();}
    }

    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);
    }

    static File getSnapshotFile(String envName, String dataId, String group, String tenant) {File tmp = new File(LOCAL_SNAPSHOT_PATH, envName + "_nacos");
        if (StringUtils.isBlank(tenant)) {tmp = new File(tmp, "snapshot");
        } else {tmp = new File(tmp, "snapshot-tenant");
            tmp = new File(tmp, tenant);
        }

        return new File(new File(tmp, group), dataId);
    }

    public static final String LOCAL_FILEROOT_PATH;
    public static final String LOCAL_SNAPSHOT_PATH;

    static {LOCAL_FILEROOT_PATH = System.getProperty("JM.LOG.PATH", System.getProperty("user.home")) + File.separator
            + "nacos" + File.separator + "config";
        LOCAL_SNAPSHOT_PATH = System.getProperty("JM.SNAPSHOT.PATH", System.getProperty("user.home")) + File.separator
            + "nacos" + File.separator + "config";
        LOGGER.info("LOCAL_SNAPSHOT_PATH:{}", LOCAL_SNAPSHOT_PATH);
    }

}
  • getFailover 方法首先会通过 getFailoverFile 获取本地配置文件,然后通过 readFile 读取;getSnapshot 方法首先通过 getSnapshotFile 获取 snapshot 文件,然后通过 readFile 读取;saveSnapshot 方法会存储新的 config;cleanAllSnapshot 方法会清除 snapshot 目录下所有缓存文件

CacheData

nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/CacheData.java

public class CacheData {
    
    //......

    public CacheData(ConfigFilterChainManager configFilterChainManager, String name, String dataId, String group) {if (null == dataId || null == group) {throw new IllegalArgumentException("dataId=" + dataId + ", group=" + group);
        }
        this.name = name;
        this.configFilterChainManager = configFilterChainManager;
        this.dataId = dataId;
        this.group = group;
        this.tenant = TenantUtil.getUserTenantForAcm();
        listeners = new CopyOnWriteArrayList<ManagerListenerWrap>();
        this.isInitializing = true;
        this.content = loadCacheContentFromDiskLocal(name, dataId, group, tenant);
        this.md5 = getMd5String(content);
    }

    public CacheData(ConfigFilterChainManager configFilterChainManager, String name, String dataId, String group,
                     String tenant) {if (null == dataId || null == group) {throw new IllegalArgumentException("dataId=" + dataId + ", group=" + group);
        }
        this.name = name;
        this.configFilterChainManager = configFilterChainManager;
        this.dataId = dataId;
        this.group = group;
        this.tenant = tenant;
        listeners = new CopyOnWriteArrayList<ManagerListenerWrap>();
        this.isInitializing = true;
        this.content = loadCacheContentFromDiskLocal(name, dataId, group, tenant);
        this.md5 = getMd5String(content);
    }

    private String loadCacheContentFromDiskLocal(String name, String dataId, String group, String tenant) {String content = LocalConfigInfoProcessor.getFailover(name, dataId, group, tenant);
        content = (null != content) ? content
            : LocalConfigInfoProcessor.getSnapshot(name, dataId, group, tenant);
        return content;
    }

    //......
}
  • CacheData 的构造器会通过 loadCacheContentFromDiskLocal 从本地磁盘加载缓存数据;loadCacheContentFromDiskLocal 方法则是通过 LocalConfigInfoProcessor.getFailover 或 LocalConfigInfoProcessor.getSnapshot 来获取数据

小结

LocalConfigInfoProcessor 的 getFailover 方法首先会通过 getFailoverFile 获取本地配置文件,然后通过 readFile 读取;getSnapshot 方法首先通过 getSnapshotFile 获取 snapshot 文件,然后通过 readFile 读取;saveSnapshot 方法会存储新的 config;cleanAllSnapshot 方法会清除 snapshot 目录下所有缓存文件

doc

  • LocalConfigInfoProcessor

正文完
 0