持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
意志坚强的人能把世界放在手中像泥块一样任意揉捏 —— 歌德
图解+源码讲解 Nacos 客户端发布配置流程
Nacos 源码分析系列相关文章
- 从零开始看 Nacos 源码环境搭建
- 图解+源码讲解 Nacos 客户端发起注册流程
- 图解+源码讲解 Nacos 服务端处理注册请求逻辑
- 图解+源码讲解 Nacos 客户端下线流程
- 图解+源码讲解 Nacos 服务端处理下线请求
- 图解+源码讲解 Nacos 客户端发起心跳请求
- 图解+源码讲解 Nacos 服务端处理心跳请求
- 图解+源码讲解 Nacos 服务端处理配置获取请求
- 图解+源码讲解 Nacos 客户端动态监听配置机制
- 图解+源码讲解 Nacos 客户端发布配置流程
代码请求示例
环境介绍
pom.xml 配置【我的环境是 springboot 的环境】
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/>
</parent>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.8-bugfix</version>
</dependency>
<!-- 其他的进行了省略 -->
复制代码
application.properties 配置
nacos.config.server-addr=nacosip地址 # IP地址
nacos.config.data-id=api.properties # data_id名称
nacos.config.group=DEFAULT_GROUP # 组信息
nacos.config.namespace=93ccfa4e-09fd-40d6-9cea-d05b4c119f3b # 名称空间ID
nacos.config.username=账号
nacos.config.password=密码
nacos.config.auto-refresh=true // 开启自动刷新
nacos.config.type=properties // 配置文件类型
复制代码
发布配置代码实现
通过实现 EnvironmentAware 接口去获取配置信息,之后通过 @NacosInjected 注解将配置对象注入进来之后通过该注入对象进行配置发布请求
@RestController
@RequestMapping("/nacos")
public class NacosController implements EnvironmentAware {
private final static String NACOS_DATA_ID = "nacos.config.data-id";
private final static String NACOS_GROUP = "nacos.config.group";
private static String dataId = "";
private static String group = "";
@NacosInjected
private ConfigService configService;
@Autowired
private Environment environment;
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@PostConstruct
private void init() {
dataId = environment.getProperty(NACOS_DATA_ID);
group = environment.getProperty(NACOS_GROUP);
}
/**
* 发布配置
*/
@RequestMapping(value = "/publishConfig",method = RequestMethod.GET)
public boolean publishConfig() {
boolean res = false;
try {
// 核心代码
res = configService.publishConfig(dataId, group, "发布配置");
} catch (NacosException e) {
e.printStackTrace();
}
System.out.println(res);
return res;
}
}
复制代码
结果展示
结果显示我们已经通过这个接口将配置信息成功的进行了发布
源码分析
核心代码块就是下面的这句话,publishConfig这个接口是 configService下面的接口,其实这个接口我们已经分析过很多次了,我们再看看这个 configService接口里面的方法
configService.publishConfig(dataId, group, "发布配置");
复制代码
configService 接口
这个方法里面有获取配置的方法、发布配置的方法、删除配置的方法、添加监听器的方法等等,我们后续都会进行分析的,先看发布配置的方法
publishConfig 发布配置
/**
* Publish config.
*
* @param dataId dataId
* @param group group
* @param content content
* @return Whether publish
* @throws NacosException NacosException
*/
boolean publishConfig(String dataId, String group, String content)throws NacosException;
复制代码
NacosConfigService 这个类实现了 ConfigService 接口
@Override
public boolean publishConfig(String dataId, String group, String content)
throws NacosException {
// ConfigType.getDefaultType().getType() 默认是text格式的
return publishConfig(dataId, group, content, ConfigType.getDefaultType().getType());
}
@Override
public boolean publishConfig(String dataId, String group, String content, String type)
throws NacosException {
return publishConfigInner(namespace, dataId, group, null, null, null, content, type);
}
复制代码
真正的发布配置方法
private boolean publishConfigInner(String tenant, String dataId, String group,
String tag, String appName,String betaIps, String content, String type)
throws NacosException {
// 创建配置请求
ConfigRequest cr = new ConfigRequest();
// 设置dataId
cr.setDataId(dataId);
// 设置租户信息
cr.setTenant(tenant);
// 设置组信息
cr.setGroup(group);
// 设置文本信息
cr.setContent(content);
......
content = cr.getContent();
// 获取请求的 URL 地址 /v1/cs/configs
String url = Constants.CONFIG_CONTROLLER_PATH;
// 拼接请求参数
Map<String, String> params = new HashMap<String, String>(6);
params.put("dataId", dataId);
params.put("group", group);
params.put("content", content);
params.put("type", type);
if (StringUtils.isNotEmpty(tenant)) {
params.put("tenant", tenant);
}
if (StringUtils.isNotEmpty(appName)) {
params.put("appName", appName);
}
if (StringUtils.isNotEmpty(tag)) {
params.put("tag", tag);
}
String dataKey = (String) cr.getParameter("encryptedDataKey");
if (StringUtils.isNotEmpty(dataKey)) {
params.put("encryptedDataKey", dataKey);
}
// 分析请求头部参数
Map<String, String> headers = new HashMap<String, String>(1);
if (StringUtils.isNotEmpty(betaIps)) {
headers.put("betaIps", betaIps);
}
HttpRestResult<String> result = null;
try {
// 发布配置的真正 Http 请求
result = agent.httpPost(url, headers, params, encode, POST_TIMEOUT);
} catch (Exception ex) {
LOGGER.warn("[{}] [publish-single] exception, dataId={},
group={}, msg={}", agent.getName(), dataId, group,
ex.toString());
return false;
}
if (result.ok()) {
LOGGER.info("[{}] [publish-single] ok, dataId={}, group={}, tenant={},
config={}", agent.getName(), dataId,
group, tenant, ContentUtils.truncateContent(content));
return true;
} else if (HttpURLConnection.HTTP_FORBIDDEN == result.getCode()) {
LOGGER.warn("[{}] [publish-single] error, dataId={}, group={},
tenant={}, code={}, msg={}", agent.getName(),
dataId, group, tenant, result.getCode(), result.getMessage());
throw new NacosException(result.getCode(), result.getMessage());
} else {
LOGGER.warn("[{}] [publish-single] error, dataId={}, group={},
tenant={}, code={}, msg={}", agent.getName(),
dataId, group, tenant, result.getCode(), result.getMessage());
return false;
}
}
复制代码
httpPost 请求方法
走的是 ServerHttpAgent 这个实现类里面的方法 通过 NACOS_RESTTEMPLATE进行HTTP 请求,getUrl(currentServerAddr, path) 这个方法就是进行地址拼接的方法
public HttpRestResult<String> httpPost(String path, Map<String, String> headers,
Map<String, String> paramValues,String encode, long readTimeoutMs)
throws Exception {
// 获取配置中心服务地址
String currentServerAddr = serverListMgr.getCurrentServerAddr();
// 这里省略了很多重试的代码操作
// ......
// 通过 NACOS_RESTTEMPLATE 发起 url 地址请求
HttpRestResult<String> result = NACOS_RESTTEMPLATE
.postForm(getUrl(currentServerAddr, path),
httpConfig, newHeaders, paramValues, String.class);
return result;
}
复制代码
小结
其实就是通过 NacosConfigService的 publishConfig方法进行配置发布操作的,通过参数拼接,比如dataID、group、等等信息之后通过 NACOS_RESTTEMPLATE进行 http 请求访问,进行配置的发布,默认的是text 格式的,你可以制定格式的比如 JSON 、XML、TEXT、HTML、YAML等格式都可以的