图解+源码讲解 Nacos 客户端发布配置流程

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

意志坚强的人能把世界放在手中像泥块一样任意揉捏 —— 歌德

图解+源码讲解 Nacos 客户端发布配置流程

Nacos 源码分析系列相关文章

  1. 从零开始看 Nacos 源码环境搭建
  2. 图解+源码讲解 Nacos 客户端发起注册流程
  3. 图解+源码讲解 Nacos 服务端处理注册请求逻辑
  4. 图解+源码讲解 Nacos 客户端下线流程
  5. 图解+源码讲解 Nacos 服务端处理下线请求
  6. 图解+源码讲解 Nacos 客户端发起心跳请求
  7. 图解+源码讲解 Nacos 服务端处理心跳请求
  8. 图解+源码讲解 Nacos 服务端处理配置获取请求
  9. 图解+源码讲解 Nacos 客户端动态监听配置机制
  10. 图解+源码讲解 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;
    }
}
复制代码

结果展示

    结果显示我们已经通过这个接口将配置信息成功的进行了发布
image.png

源码分析

    核心代码块就是下面的这句话,publishConfig这个接口是 configService下面的接口,其实这个接口我们已经分析过很多次了,我们再看看这个 configService接口里面的方法

configService.publishConfig(dataId, group, "发布配置");
复制代码

configService 接口

image.png     这个方法里面有获取配置的方法、发布配置的方法、删除配置的方法、添加监听器的方法等等,我们后续都会进行分析的,先看发布配置的方法

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 接口
image.png

@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 这个实现类里面的方法image.png     通过 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;
}

复制代码

小结

    其实就是通过 NacosConfigServicepublishConfig方法进行配置发布操作的,通过参数拼接,比如dataIDgroup、等等信息之后通过 NACOS_RESTTEMPLATE进行 http 请求访问,进行配置的发布,默认的是text 格式的,你可以制定格式的比如 JSON 、XML、TEXT、HTML、YAML等格式都可以的

猜你喜欢

转载自juejin.im/post/7109026741439430686