Nacos 服务注册的原理

转载:Nacos 服务注册的原理

1. Nacos 服务注册需要具备的能力

  • 服务提供者把自己的协议地址注册到Nacos server

  • 服务消费者需要从Nacos Server上去查询服务提供者的地址(根据服务名称)

  • Nacos Server需要感知到服务提供者的上下线的变化

  • 服务消费者需要动态感知到Nacos Server端服务地址的变化

  作为注册中心所需要的能力大多如此,我们需要做的是理解各种注册中心的独有特性,总结他们的共性。

2. Nacos的实现原理

下面我们先来了解一下 Nacos 注册中心的实现原理,通过下面这张图来说明。

2021-04-15-2jRzYs

图中的流程是大家所熟悉的,不同的是在Nacos 中,服务注册时在服务端本地会通过轮询注册中心集群节点地址进行服务得注册,在注册中心上,即Nacos Server上采用了Map保存实例信息,当然配置了持久化的服务会被保存到数据库中,在服务的调用方,为了保证本地服务实例列表的动态感知,Nacos与其他注册中心不同的是,采用了 Pull/Push同时运作的方式。通过这些我们对Nacos注册中心的原理有了一定的了解。我们从源码层面去验证这些理论知识。

3. Nacos的源码分析(结合spring-cloud-alibaba +dubbo +nacos 的整合)

3.1 服务注册的流程

在基于Dubbo服务发布的过程中, 自动装配是走的事件监听机制,在 DubboServiceRegistrationNonWebApplicationAutoConfiguration 这个类中,这个类会监听 ApplicationStartedEvent 事件,这个事件是spring boot在2.0新增的,就是当spring boot应用启动完成之后会发布这个时间。而此时监听到这个事件之后,会触发注册的动作。

this.serviceRegistry。 是spring-cloud提供的接口实现(org.springframework.cloud.client.serviceregistry.ServiceRegistry).很显然注入的实例是: NacosServiceRegistry

2021-04-15-aC7lIf

然后进入到实现类的注册方法:

接下去就是开始注册实例,主要做两个动作

  1. 如果当前注册的是临时节点,则构建心跳信息,通过beat反应堆来构建心跳任务

  2. 调用registerService发起服务注册

然后调用 NamingProxy 的注册方法进行注册,代码逻辑很简单,构建请求参数,发起请求。

往下走我们就会发现上面提到的,服务在进行注册的时候会轮询配置好的注册中心的地址:

最后通过 callServer(api, params, server, method) 发起调用,这里通过 JSK自带的 HttpURLConnection 进行发起调用。我们可以通过断点的方式来看到这里的请求参数:

2021-04-15-SlG1A4

期间可能会有多个 GET的请求获取服务列表,是正常的,会发现有如上的一个请求,会调用 http://192.168.200.1:8848/nacos/v1/ns/instance 这个地址。那么接下去就是Nacos Server 接受到服务端的注册请求的处理流程。需要下载Nacos Server 源码,

源码下载可以参考 :https://www.cnblogs.com/wuzhenzhao/p/11384266.html

3.2 Nacos服务端的处理

服务端提供了一个InstanceController类,在这个类中提供了服务注册相关的API,而服务端发起注册时,调用的接口是: [post]: /nacos/v1/ns/instance ,serviceName: 代表客户端的项目名称 ,namespace: nacos 的namespace。

然后调用 ServiceManager 进行服务的注册。

在创建空的服务实例的时候我们发现了存储实例的map:

在 getService 方法中我们发现了Map:

通过注释我们可以知道,Nacos是通过不同的 namespace 来维护服务的,而每个namespace下有不同的group,不同的group下才有对应的Service ,再通过这个 serviceName 来确定服务实例。

第一次进来则会进入初始化,初始化完会调用 putServiceAndInit.

获取到服务以后把服务实例添加到集合中,然后基于一致性协议进行数据的同步。然后调用 addInstance.

然后给服务注册方发送注册成功的响应。结束服务注册流程。其中细节后续慢慢分析。

最后更新于

这有帮助吗?