1.启动配置本地服务请参考上一节:nacos 1.4.0 快速开始
2.新建配置
接下来我们在控制台上创建一个简单的配置项,如下图所示:
namespace、group、dataId含义如下:
3.启动客户端
当服务端以及配置项都准备好之后,就可以创建客户端了,如下图所示新建一个 Nacos 的 ConfigService 来接收数据:
执行后将打印如下信息:
这里我用了一个 System.in.read() 方法来监听输入的信息,主要是为了防止主线程退出,看不到后续的测试结果。
4.修改配置信息
接下来我们在 Nacos 的控制台上将我们的配置信息改为如下图所示:
修改完配置,点击 “发布” 按钮后,客户端将会收到最新的数据,如下图所示:
至此一个简单的动态配置管理功能已经讲完了,删除配置和更新配置操作类似,这里不再赘述。
5.适用场景
了解了动态配置管理的效果之后,我们知道了大概的原理了,Nacos 服务端保存了配置信息,客户端连接到服务端之后,根据 dataID,group可以获取到具体的配置信息,当服务端的配置发生变更时,客户端会收到通知。当客户端拿到变更后的最新配置信息后,就可以做自己的处理了,这非常有用,所有需要使用配置的场景都可以通过 Nacos 来进行管理。
可以说 Nacos 有很多的适用场景,包括但不限于以下这些情况:
- 数据库连接信息
- 限流规则和降级开关
- 流量的动态调度
6.推还是拉
现在我们了解了 Nacos 的配置管理的功能了,但是有一个问题我们需要弄明白,那就是 Nacos 客户端是怎么实时获取到 Nacos 服务端的最新数据的。
其实客户端和服务端之间的数据交互,无外乎两种情况:
- 服务端推数据给客户端
- 客户端从服务端拉数据
那到底是推还是拉呢,从 Nacos 客户端通过 Listener 来接收最新数据的这个做法来看,感觉像是服务端推的数据,但是不能想当然,要想知道答案,最快最准确的方法就是从源码中去寻找。
7.创建 ConfigService
从我们的 demo 中可以知道,首先是创建了一个 ConfigService。而 ConfigService 是通过 ConfigFactory 类创建的,如下图所示:
/**
* Create Config.
*
* @param properties init param
* @return ConfigService
* @throws NacosException Exception
*/
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 的构造方法来创建 ConfigService 的,而且是有一个 Properties 参数的构造方法。
需要注意的是,这里并没有通过单例或者缓存技术,也就是说每次调用都会重新创建一个 ConfigService的实例。
8.实例化 ConfigService
现在我们来看下 NacosConfigService 的构造方法,看看 ConfigService 是怎么实例化的,如下图所示:
/**
* http agent.
*/
private final HttpAgent agent;
/**
* long polling.
*/
private final ClientWorker worker;
private String namespace;
private final String encode;
private final ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager();
public NacosConfigService(Properties properties) throws NacosException {
ValidatorUtils.checkInitParam(properties);
String encodeTmp = properties.getProperty(PropertyKeyConst.ENCODE);
if (StringUtils.isBlank(encodeTmp)) {
this.encode = Constants.ENCODE;
} else {
this.encode = encodeTmp.trim();
}
initNamespace(properties);
this.agent = new MetricsHttpAgent(new ServerHttpAgent(properties));
this.agent.start();
this.worker = new ClientWorker(this.agent