Nacos配置中心客户端源码分析(二): 客户端和服务端交互

本文收录于专栏 Nacos
推荐阅读:Nacos 架构 & 原理
⚠️:使用的Nacos版本为2.3.X


前言

上篇文章我们简单看了看Nacos客户端在启动的时候,初始化本地配置的大致流程。
本篇我们开始逐渐深入细节,先从客户端和服务端交互的相关代码入手。


一、NacosConfigLoader

上篇中我们也提到了客户端从服务端获取配置的代码:
在这里插入图片描述
这个nacosConfig就是从服务端获取到的,我们看下这个load()做了什么。

public String load(String dataId, String groupId, Properties nacosProperties) throws RuntimeException {
	try {
		//获取ConfigService
		configService = nacosServiceFactory != null
				? nacosServiceFactory.createConfigService(nacosProperties)
				: NacosFactory.createConfigService(nacosProperties);
	}
	catch (NacosException e) {
		throw new RuntimeException("ConfigService can't be created with dataId :"
				+ dataId + " , groupId : " + groupId + " , properties : "
				+ nacosProperties, e);
	}
	//拿到服务端的配置内容
	return NacosUtils.getContent(configService, dataId, groupId);
}

NacosUtils.getContent的实现逻辑就是从configService中获取数据:

String content = null;
try {
	content = configService.getConfig(dataId, groupId, DEFAULT_TIMEOUT);
}

二、NacosConfigService

@Override
public String getConfig(String dataId, String group, long timeoutMs) throws NacosException {
    return getConfigInner(namespace, dataId, group, timeoutMs);
}

getConfigInner代码如下:

private String getConfigInner(String tenant, String dataId, String group, long timeoutMs) throws NacosException {
    group = blank2defaultGroup(group);
    ParamUtils.checkKeyParam(dataId, group);
    ConfigResponse cr = new ConfigResponse();
    
    cr.setDataId(dataId);
    cr.setTenant(tenant);
    cr.setGroup(group);
    
    // We first try to use local failover content if exists.
    // A config content for failover is not created by client program automatically,
    // but is maintained by user.
    // This is designed for certain scenario like client emergency reboot,
    // changing config needed in the same time, while nacos server is down.
    String content = LocalConfigInfoProcessor.getFailover(worker.getAgentName(), dataId, group, tenant);
    if (content != null) {
        LOGGER.warn("[{}] [get-config] get failover ok, dataId={}, group={}, tenant={}, config={}",
                worker.getAgentName(), dataId, group, tenant, ContentUtils.truncateContent(content));
        cr.setContent(content);
        String encryptedDataKey = LocalEncryptedDataKeyProcessor
                .getEncryptDataKeyFailover(agent.getName(), dataId, group, tenant);
        cr.setEncryptedDataKey(encryptedDataKey);
        configFilterChainManager.doFilter(null, cr);
        content = cr.getContent();
        return content;
    }
    
    try {
        ConfigResponse response = worker.getServerConfig(dataId, group, tenant, timeoutMs, false);
        cr.setContent(response.getContent());
        cr.setEncryptedDataKey(response.getEncryptedDataKey());
        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={}",
                worker.getAgentName(), dataId, group, tenant, ioe.toString());
    }

    content = LocalConfigInfoProcessor.getSnapshot(worker.getAgentName(), dataId, group, tenant);
    if (content != null) {
        LOGGER.warn("[{}] [get-config] get snapshot ok, dataId={}, group={}, tenant={}, config={}",
                worker.getAgentName(), dataId, group, tenant, ContentUtils.truncateContent(content));
    }
    cr.setContent(content);
    String encryptedDataKey = LocalEncryptedDataKeyProcessor
            .getEncryptDataKeySnapshot(agent.getName(), dataId, group, tenant);
    cr.setEncryptedDataKey(encryptedDataKey);
    configFilterChainManager.doFilter(null, cr);
    content = cr.getContent();
    return content;
}

以上这个方法是客户端获取config data的方法,我们可以从其中看出三个获取配置的方式:

  1. LocalConfigInfoProcessor.getFailover:从客户端本地一个文件中尝试获取配置,这种方式用于服务故障时临时使用。可以直接在指定地址创建文件,客户端启动时,会优先从此文件获取配置。
  2. ConfigResponse response = worker.getServerConfig(dataId, group, tenant, timeoutMs, false):请求Nacos服务端,获取配置数据。
  3. LocalConfigInfoProcessor.getSnapshot(worker.getAgentName(), dataId, group, tenant); :从本地快照中获取数据。

三、ClientWorker

上文中我们看到了客户端从服务端获取数据的代码:ConfigResponse response = worker.getServerConfig(dataId, group, tenant, timeoutMs, false)。我们接下来看看这个类是如何从服务端获取数据的。
在这里插入图片描述
这里可以看到是最终是发起了一个GRPC请求去服务端获取数据。

四、服务端处理逻辑

之前梳理服务注册时,我们了解过服务端处理GRPC请求的入口类:GrpcRequestAcceptor
处理请求的主要逻辑如下:

  1. 从请求中获取请求类型type
  2. 根据type获取处理当前请求的处理类:RequestHandler requestHandler = requestHandlerRegistry.getByRequestType(type);
  3. 处理请求,获取结果:Response response = requestHandler.handleRequest(request, requestMeta);

当前请求的处理类是:ConfigQueryRequestHandler
这个类会从server端的本地缓存或者指定数据库去获取配置数据。

总结

本篇我们简单梳理了客户端和服务端在获取配置时的大致流程。可以看到客户端在启动时,优先从客户端本地去尝试获取数据,获取不到时,才会请求服务端去获取数据。

  • 12
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Nacos配置中心控制台的源码分析可以帮助我们深入理解其实现细节和工作原理。以下是一个大致的源码分析过程: 1. 入口类分析:首先,我们需要找到Nacos配置中心控制台的入口类。该类通常是一个Spring Boot应用的启动类,负责初始化和启动整个应用。我们可以查找包含main方法的类,或者在启动脚本中找到应用的入口点。 2. 依赖分析:接下来,我们需要分析应用所依赖的第三方库和框架。查看应用的pom.xml文件或者build.gradle文件,可以获取到所依赖的各个库和对应版本。这些依赖通常包括Spring框架、Nacos客户端等。 3. 配置加载与解析:Nacos配置中心控制台需要加载和解析配置,包括数据库配置、Nacos服务地址配置等。我们可以查找相关的配置文件或者代码片段,了解配置的加载和解析过程。 4. 控制器与路由:控制台通常提供了一些Web接口供前端调用。我们可以查找控制器类,分析其中的方法和注解,了解各个接口的功能和路由规则。 5. 页面模板与前端交互配置中心控制台通常包含一些页面模板和与前端的交互逻辑。我们可以查找相关的HTML、CSS和JavaScript文件,分析页面的结构和交互逻辑。 6. 调用Nacos API:控制台需要与Nacos服务器进行通信,调用Nacos的API获取和修改配置信息。我们可以查找相关的API调用,了解控制台是如何与Nacos服务器进行通信的。 通过以上分析,我们可以逐步了解Nacos配置中心控制台的实现细节和工作原理。需要注意的是,具体的源码分析过程会因项目结构和代码风格而有所不同。以上只是一个大致的指导,具体分析还需根据实际情况来进行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高级摸鱼工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值