前言
很久没发过文了,最近抽空研究了下nacos,准备写一期关于nacos的相关文章,用于后续查阅复习
搭建
本地搭建了一套nacos的项目,这里为了用于研究源码,下载了nacos的源码,正常使用的话直接用jar就行,可以去https://github.com/alibaba/nacos下载Nacos源码,我本地就直接拿了个1.4.2试了试
首先解释一下,Nacos底层的数据通信会基于protobuf对数据做序列化和反序列化。并将对应的proto文件定义在了consistency这个子模块中:
利用protoc编译proto后就可以启动了,本篇只分析源码不涉及具体使用
这里这个protoc是Protocol Buffers的编译器,ProtoBuf 目前gRPC,Google ,Kubernetes等等都在用,比json更好用,可以去官网或者github,地址为
https://github.com/protocolbuffers/protobuf/releases
服务注册源码分析
Nacos提供了服务注册的API接口,客户端只需要向该接口发送请求,即可实现服务注册。我们直接从代码来看。
因为Nacos的客户端是基于SpringBoot的自动装配实现的,我们可以在nacos-discovery依赖:spring-cloud-starter-alibaba-nacos-discovery-2.2.6.RELEASE.jar
这个包中找到Nacos自动装配信息:
这里指的是加载的自动配置类,其中包括了NacosServiceRegistryAutoConfiguration
这个类,直接点进去,翻到下面
这里找到了一个和自动注册有关的Bean,点NacosAutoServiceRegistration
进去继续看
这里可以看到其父类AbstractAutoServiceRegistration
也被初始化了,点父类进去继续看
这里看到AbstractAutoServiceRegistration
实现了ApplicationListener
接口,监听Spring容器启动过程中的事件。
在监听到WebServerInitializedEvent
(web服务初始化完成)的事件后,执行了bind
方法。 WebServerInitializedEvent
是 Spring Framework 中的一个事件,用于监听Web服务器初始化完成的事件。当Web服务器初始化完成后,会触发该事件,并执行对应的监听器方法。这里执行start
解读一下,当前服务处于未运行状态时,才进行初始化,然后发布服务开始注册的事件,开始注册,等发布注册完成事件后设置服务状态为运行状态,基于AtomicBoolean。这里我们点进去register()
NacosServiceRegistry
是Spring的ServiceRegistry
接口的实现类,而ServiceRegistry接口是服务注册、发现的规约接口,定义了register、deregister等方法的声明。这里的方法中最终是调用NamingService的registerInstance方法实现注册的。而NacosNamingService
提供了服务注册、订阅等功能。继续点击registerInstance
可以看到最终由NacosProxy的registerService方法,完成服务注册,我们看下具体的注册过程,继续点registerService进去
可以看到这里提交的信息就是Nacos服务注册接口需要的完整参数,核心参数包括了
- NAMESPACE_ID环境
- SERVICE_NAME服务名称
- GROUP_NAME组名称
- CLUSTER_NAME集群名称
- ip当前实例的ip地址
- port当前实例的端口
另外这里是与服务心跳有关的代码,后续有空了再研究一下,以上是关于客户端服务注册的源码分析部分
详细注册流程
流程图
核心类交互解析
1.NacosAutoServiceRegistration
- 继承自 AbstractAutoServiceRegistration
- 负责触发自动注册入口
- 关键方法:register()
2.AbstractAutoServiceRegistration
- 实现 ApplicationListener
- 监听 Web 服务器初始化完成事件
- 事件触发时调用 start() 方法
- 核心逻辑:
public void register(Registration registration) {
namingService.registerInstance(
registration.getServiceId(),
group,
createInstance(registration)
);
}
3.NacosServiceRegistry
- 实现 ServiceRegistry 接口
- 委托给 NamingService 执行注册
- 关键注册逻辑:
public void registerInstance(String serviceName, String groupName, Instance instance) {
serverProxy.registerService(serviceName, groupName, instance);
// 启动心跳
beatReactor.addBeatInfo(serviceName, beatInfo);
}
4.调用栈:
AbstractAutoServiceRegistration.start()
└── NacosAutoServiceRegistration.register()
└── NacosServiceRegistry.register()
└── NacosNamingService.registerInstance()
├── NamingProxy.registerService() // HTTP请求封装
├── BeatReactor.addBeatInfo() // 初始化心跳
└── BeatTask.run() // 心跳任务
另外事件驱动注册,心跳守护线程,故障恢复机制,元数据处理等等后续有空了再补充
5.版本特性
Nacos 1.x和Nacos 2.x的特性不太一样,这里也说下吧
- Nacos 1.x:使用 HTTP 轮询 + UDP 推送
- Nacos 2.x:默认采用 gRPC 长连接(通过 NamingGrpcClientProxy 实现)
- 兼容模式:通过 namingLoadCacheAtStart 配置支持冷启动缓存