Nacos源码剖析
Nacos源码有很多值得我们学习的地方,为了深入理解Nacos,我们剖析源码,分析如下2个知识点:
1:Nacos对注册中心的访问原理
2:Nacos注册服务处理流程
源码环境搭建
1、从官方项目上克隆下来,并且检出 1.4.1 版本,导入idea。nacos源码环境搭建起来比较轻松,几乎不会报什么错误,导入后编译安装到本地环境即可
2、找到config
模块中找到 \resources\META-INF\nacos-db.sql
,在本地mysql中创建数据库nacos-config
,将该脚本导入执行创建表。
3、找到console
模块下的配置文件application.properties
,修改相关配置
#*************** Config Module Related Configurations ***************#
### If use MySQL as datasource:
spring.datasource.platform=mysql
### Count of DB:
db.num=1
### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos-config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=nacos
db.password.0=nacos
4、找到console
模块下的启动类,启动nacos的服务端,启动时添加启动参数,指定启动模式为非集群启动
-Dnacos.standalone=true
5、访问本地的nacos:http://localhost:8848/nacos
至此,源码环境搭建成功!
nacos客户端
首先要搞清楚:nacos的客户端其实在我们自己的服务里,我们引入了nacos的相关坐标依赖,nacos客户端以jar包的形式在我们的服务中工作
对于nacos的客户端,它都要帮我们实现什么功能呢?
它的主要工作有:服务注册、服务发现、服务下线操作、服务订阅操作等相关操作。
客户端与注册中心服务端的交互,主要集中在服务注册、服务下线、服务发现、订阅某个服务,其实使用最多的就是服务注册和服务发现,下面我会从源码的角度分析一下这四个功能。
在Nacos源码中nacos-example
中com.alibaba.nacos.example.NamingExample
类分别演示了这4个功能的操作,我们可以把它当做入口,代码如下:
public class NamingExample {
public static void main(String[] args) throws NacosException {
Properties properties = new Properties();
properties.setProperty("serverAddr", System.getProperty("serverAddr"));
properties.setProperty("namespace", System.getProperty("namespace"));
NamingService naming = NamingFactory.createNamingService(properties);
//服务注册
naming.registerInstance("nacos.test.3", "11.11.11.11", 8888, "TEST1");
naming.registerInstance("nacos.test.3", "2.2.2.2", 9999, "DEFAULT");
//服务发现
System.out.println(naming.getAllInstances("nacos.test.3"));
//服务下线
naming.deregisterInstance("nacos.test.3", "2.2.2.2", 9999, "DEFAULT");
System.out.println(naming.getAllInstances("nacos.test.3"));
//服务订阅
Executor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("test-thread");
return thread;
}
});
naming.subscribe("nacos.test.3", new AbstractEventListener() {
//EventListener onEvent is sync to handle, If process too low in onEvent, maybe block other onEvent callback.
//So you can override getExecutor() to async handle event.
@Override
public Executor getExecutor() {
return executor;
}
@Override
public void onEvent(Event event) {
System.out.println(((NamingEvent) event).getServiceName());
System.out.println(((NamingEvent) event).getInstances());
}
});
}
}
1.1.1 服务注册
我们沿着案例中的服务注册方法调用找到nacos-api
中的NamingService.registerInstance()
并找到它的实现类和方法com.alibaba.nacos.client.naming.NacosNamingService
,代码如下:
/***
* 服务注册
* @param serviceName 服务名字
* @param ip 服务IP
* @param port 服务端口
* @param clusterName 集群名字
* @throws NacosException
*/
@Override
public void registerInstance(String serviceName, String ip, int port, String clusterName) throws NacosException {
registerInstance(serviceName, Constants.DEFAULT_GROUP, ip, port, clusterName);
}