上一章节,我们从全局了解了一下Nacos项目的模块架构,做到了心中有数,现在,我们去逐步去挖掘里面的代码细节,很多人在学习开源的时候,无从下手,代码那么多,从哪个地方开始看呢?我们可以从一个接口开始入手,这个接口是你使用过的,知道它大概做什么事,有体感的,大家还记得第一章时,我们写的HelloWorld吗,对,就从里面的接口开始剥洋葱。
加入阿里巴巴中间件开发者群,微信添加“zjjxg2018”,并备注公司-城市信息。
https://github.com/alibaba/nacos,这个是Nacos的github代码地址,开始之前先start关注一下,加上watch,后续Nacos的邮件列表也会通知到你,可以关注到Nacos的最新实时消息,及各大牛之间的精彩讨论。
下面这段代码,是第一章节发布一个服务的代码:
public static void main(String[] args) throws NacosException, InterruptedException {
//发布的服务名
String serviceName = "helloworld.services";
//构造一个Nacos实例,入参是Nacos server的ip和服务端口
NamingService naming = NacosFactory.createNamingService("100.81.0.34:8080");
//发布一个服务,该服务对外提供的ip为127.0.0.1,端口为8888
naming.registerInstance(serviceName, "100.81.0.35", 8080);
Thread.sleep(Integer.MAX_VALUE);
}
其中,第一步,是构造一个Nacos服务实例,构造实例的入参,是一个String,值的规范为ip:port,这个ip,就是我们任意一台Nacos server的地址,我们点进去看这个方法:
public static NamingService createNamingService(String serverAddr) throws NacosException {
return NamingFactory.createNamingService(serverAddr);
}
同时我们看下创建配置服务实例的代码:
public static ConfigService createConfigService(String serverAddr) throws NacosException {
return ConfigFactory.createConfigService(serverAddr);
}
我们可以看到,NacosFactory实际上是一个服务发现和配置管理接口的统一入口,再由它不通的方法,创建不同服务的实例,我们可以直接使用NamingFactory,或者ConfigFactory直接创建Nacos的服务实例,也能work
接下来,看一下,是如何构造出这个Nacos naming实例的:
public static NamingService createNamingService(String serverList) throws NacosException {
try {
Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.naming.NacosNamingService");
Constructor constructor = driverImplClass.getConstructor(String.class);
NamingService vendorImpl = (NamingService) constructor.newInstance(serverList);
return vendorImpl;
} catch (Throwable e) {
throw new NacosException(-400, e.getMessage());
}
}
通过反射实例化出了一个NamingService的实例NacosNamingService,构造器是一个带String入参的,我们顺着往下看,构造函数里面做了哪些事情:
public NacosNamingService(String serverList) {
this.serverList = serverList;
init();
eventDispatcher = new EventDispatcher();
serverProxy = new NamingProxy(namespace, endpoint, serverList);
beatReactor = new BeatReactor(serverProxy);
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir);
}
入参serverList就是我们刚才传入的服务端地址,值赋给了实例的serverList字段,接下来调用了一个init方法,这个方法里面如下:
private void init() {
namespace = System.getProperty(PropertyKeyConst.NAMESPACE);
if (StringUtils.isEmpty(namespace)) {
namespace = UtilAndComs.DEFAULT_NAMESPACE_ID;
}
logName = System.getProperty(UtilAndComs.NACOS_NAMING_LOG_NAME);
if (StringUtils.isEmpty(logName))