作者:石臻臻, CSDN博客之星Top5、Kafka Contributor 、nacos Contributor、华为云 MVP ,腾讯云TVP, 滴滴Kafka技术专家 、 KnowStreaming。
KnowStreaming 是滴滴开源的Kafka运维管控平台, 有兴趣一起参与参与开发的同学,但是怕自己能力不够的同学,可以联系我,当你导师带你参与开源! 。
上一篇文章讲了 【Nacos源码之配置管理 八】客户端怎么获取服务端集群列表 ,客户端获取到集群列表缓存在内存中,是在获取配置的时候需要使用的; 因为要去服务端发起http请求获取数据; 那么我们今天来分析一下,客户端是如何获取服务端数据的 阅读完本文,您将会了解以下问题:
客户端的数据是去服务端获取的,所以我们如果不启动服务端,那么客户端也就获取不到数据;所以要先启动服务端; 如何启动 参考 【Nacos源码之配置管理 一】阅读源码第一步,本地启动Nacos
我们创建一个新SpringBoot项目; 用Nacos的sdk获取配置数据;
然后启动项目;打上断点开始调试;
这个方法会获取一个ConfigService的实例NacosConfigService;是通过返回创建的实例
public static ConfigService createConfigService(Properties properties) throws NacosException {
try {
Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.config.NacosConfigService");
Constructor constructor = driverImplClass.getConstructor(Properties.class);
ConfigService vendorImpl = (ConfigService) constructor.newInstance(properties);
return vendorImpl;
} catch (Throwable e) {
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
}
}
NacosConfigService是客户端的一个配置服务类; 所有对配置数据的操作都是这个实例来完成的;它里面持有一个ServerHttpAgent实例;ServerHttpAgent是一个Http代理类,用来发起Http请求的;它做了一些数据采集的功能 ;ServerHttpAgent中又持有一个ServerListManager实例,它负责所有的集群列表信息;就是上一篇文章解析过的; 【Nacos源码之配置管理 八】客户端怎么获取服务端集群列表
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);
properties.put("namespace","dev");
ConfigService configService = NacosFactory.createConfigService(properties);
String content = configService.getConfig(dataId, group, 5000);
System.out.println(content);
配置中设置了serverAddr 和命名空间namespace 这个命名空间可以在管理后台自己新建的
获取配置的核心代码
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 {
content = worker.getServerConfig(dataId, group, tenant, timeoutMs);
cr.setContent(content);
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;
}
从代码中可以看到调用了LocalConfigInfoProcessor.getFailover方法
String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
这个方法主要作用就是查询客户端本地的配置; 这个适和什么使用场景呢? 例如我们本地开发调试的时候,为了不影响其他开发者,所以需要每个开发者使用自己单独的配置;这个时候我们就可以在本地配置一份属于自己的配置数据; 客户端会优先读取;
这个路径真的是有一点恶心;挺长的,不太容易配置; ①.如果配置了tenant(就是命名空间namespace)
/{LOCAL_SNAPSHOT_PATH}/{serverName}_nacos/data/config-data-tenant/{tenant}/{group}/{dataId}
②.没有配置tenant
/{LOCAL_SNAPSHOT_PATH}/{serverName}_nacos/data/config-data/{group}/{dataId}
以上用括号{} 起来的参数都是入参;现在一一分析这些入参
name= /Users/shirenchuang/fixed-127.0.0.1_8848-test.shiyi.com-127.0.0.1_8849-dev_nacos/data/config-data/DEFAULT_GROUP/com.shirc.test.dataId
2. 使用方式二;配置了namespace=dev;endpoint=shiyi.com
name= /Users/shirenchuang/shiyi.com-dev/data/config-data/DEFAULT_GROUP/com.shirc.test.dataId
所以,如果使用方式一的话,是不是觉得配置一下本地数据真的挺坑爹的;
所以觉得自己一个个拼接地址容易出错,那么你可以启动的时候在LocalConfigInfoProcessor.getFailoverFile 打个断点直接拿一下它要读取的地址,如下
那么最终的文件地址就是 /Users/shirenchuang/nacos/config/fixed-172.16.10.61_8848_nacos/data/config-data/DEFAULT_GROUP/dataId文件名;
路径找到了,然后在这个路径下面创建你的dataId文件, 因为在启动的时候 nacos会自动的把数据dump到本地存放了一份快照文件,我们可以直接把这个快照dataId文件copy到刚刚的路径,再修改本地的一些配置;
如果本地没有配置配置文件的话,那么客户端就会想服务端发起Http请求去获取配置数据了;
public String getServerConfig(String dataId, String group, String tenant, long readTimeout)
throws NacosException {
/**以下省略了部分代码**/
HttpResult result = null;
try {
List params = null;
if (StringUtils.isBlank(tenant)) {
params = Arrays.asList("dataId", dataId, "group", group);
} else {
params = Arrays.asList("dataId", dataId, "group", group, "tenant", tenant);
}
result = agent.httpGet(Constants.CONFIG_CONTROLLER_PATH, null, params, agent.getEncode(), readTimeout);
} catch (IOException e) {
}
switch (result.code) {
case HttpURLConnection.HTTP_OK:
LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, result.content);
return result.content;
case HttpURLConnection.HTTP_NOT_FOUND:
LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, null);
return null;
case HttpURLConnection.HTTP_CONFLICT: {
}
case HttpURLConnection.HTTP_FORBIDDEN: {
}
default: {
}
}
}
以上获取服务端数据的流程是:
上面在从服务端获取到数据之后,会保存一份快照数据到本地中; 保存这个本地快照Snapshot有什么用呢? 这个就是为了预防服务端全部不可访问、宕机之后还能从本地快照中获取上一次获取到的数据;
在这里插入图片描述
客户端发起请求获取配置数据的时候并不会立马请求服务端中的数据
而是先查找自己本地有没有配置文件; 如果有 直接返回本地配置 如果没有才去查服务端中的配置数据; 查询到了之后还会在本地创建一个 快照文件Snapshot;这个快照文件就是防止服务端宕机获取不到数据的时候,可以去获取本地快照Snapshot返回;
留言与评论(共有 0 条评论) “” |