文章目录
- 前提介绍
- Nacos源码下载
- Nacos客户端源码
- Spring Cloud Starter Nacos 源码
- Nacos服务端源码
前提介绍
服务注册与发现作用主要是为了更好的管理众多的服务,不论Nacos还是Zookeeper、Eureka,作为注册中心都是为了解决以下两个问题:
- 屏蔽、解耦服务之间相互依赖的细节。服务之间的远程调用必须要知道IP、端口信息,一旦这些信息改变,调用方都需要更新,依赖性太强。
- 微服务架构中,服务众多、服务之间的相互依赖错综复杂,无论是服务停止、上线,还是扩容,都需要尽快通知调用方。注册中心作用就是对微服务进行动态配置,解决这一问题。
Nacos作为注册中心其本质是作为服务端,提供接口进行客户端实例的注册存储实例信息,通过心跳机制保证实例的存活,实例通过服务端发现获取其他实例信息。
本文通过Nacos源码了解服务注册与发现原理。
Nacos源码下载
下载Nacos源码
将源码导入Idea中,工程结构如下

逻辑架构如下图

Nacos客户端源码
服务实例是如何注册到Nacos的?通过源码提供的示例NamingExample.java可以看到一个服务注册到Nacos只需几行代码

NamingService作为注册中心客户端的接口,包括注册实例、注销实例、获取实例等接口,也就是服务注册/发现的功能。通过createNamingService方法可以看到其实现为NacosNamingService

在NacosNamingService.java中可以看到registerInstance的具体实现。通过代码追踪可以看到最终通过clientProxy去调用注册服务接口。

这个clientProxy是在NacosNamingService实例的时候进行了声明

NamingClientProxyDelegate.java中可以看到有grpc和http两种协议去和Nacos进行通信。

如果注册为临时实例使用grpc,永久实例使用http,在调用时会根据实例的属性选择。

所以最终向Nacos服务端注册服务、注销服务、获取实例列表等通过NamingGrpcClientProxy.java 或 NamingHttpClientProxy.java调用。整体的链路是比较简单清晰的。

Spring Cloud Starter Nacos 源码
通过上面的示例可以看到通过简单的几行代码就可以实现服务注册、发现等功能,但是我们在使用Nacos时通常基于Spring Cloud结合使用。一般在引入相关依赖,添加几个配置之后会发现服务自动注册到Nacos了,这是如何实现的?
在引入nacos注册发现依赖后可以看到该包下面的spring.factories文件,根据Spring Boot自动装配原理,首先会加载EnableAutoConfiguration对应的类,服务注册就找NacosServiceRegistryAutoConfiguration这个类。

在NacosServiceRegistryAutoConfiguration类中的这些Bean会交给Spring管理,服务注册是通过NacosAutoServiceRegistration注入实现。

NacosAutoServiceRegistration 继承了AbstractAutoServiceRegistration,而AbstractAutoServiceRegistration实现了ApplicationListener,所以在项目启动的时候会执行onApplicationEvent

当调用start()方法后最终会指向NacosServiceRegistry的register方法

可以看到register方法中的代码最终还是会通过NamingService进行服务注册,也就是服务通过API注册时的流程。
Nacos服务端源码
当客户端发送请求后,Nacos服务端接收并响应,在naming项目中有个controllers包,用来接收客户端的请求

InstanceController是实例相关的接口,其中register方法把接收到的信息解析成instance,然后调用registerInstance方法完成注册,该方法是服务端注册的核心

在nacos2.0以后新增了Client模型,一个服务gRPC长连接对应一个Client,用来管理服务注册发布、服务心跳、服务订阅等操作

通过clientOperationService的实现EphemeralClientOperationServiceImpl调用registerInstance将服务与Client、Nacos服务三者绑定,完成注册。




















