写点什么

nacos 注册中心之服务注册

作者:周杰伦本人
  • 2022 年 7 月 18 日
  • 本文字数:2040 字

    阅读完需:约 7 分钟

5 nacos 注册中心之服务注册

这篇文章是基于 nacos 1.1.4 的源码进行分析的


Nacos 提供了 SDK 和 Open API 的形式实现服务注册,两种方式本质都是一样的,SDK 方式提供了一种访问的封装,底层是基于 HTTP 协议完成请求的,所有我们直接基于 Open API 请求方式分析一下服务端的服务注册原理。


/nacos/v1/ns/instance
复制代码


服务注册对外提供的服务接口请求地址为 nacos/v1/ns/instance,实现代码为 nacos-naming 下的 InstanceController 类:


@RestController@RequestMapping(UtilsAndCommons.NACOS_NAMING_CONTEXT + "/instance")public class InstanceController {    @CanDistro    @PostMapping    public String register(HttpServletRequest request) throws Exception {
String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME); String namespaceId = WebUtils.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
serviceManager.registerInstance(namespaceId, serviceName, parseInstance(request)); return "ok"; }}
复制代码


调用 registerInstance 方法:


public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
createEmptyService(namespaceId, serviceName, instance.isEphemeral());
Service service = getService(namespaceId, serviceName);
if (service == null) { throw new NacosException(NacosException.INVALID_PARAM, "service not found, namespace: " + namespaceId + ", service: " + serviceName); }
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);}
复制代码


  1. 创建一个空服务,实际是初始化 serviceMap

  2. getService:从 serviceMap 中根据 namespaceId 和 serviceName 得到服务对象

  3. 调用 addInstance 添加服务实例。

createEmptyService

createEmptyService 用来创建空服务,调用 createServiceIfAbsent


public void createServiceIfAbsent(String namespaceId, String serviceName, boolean local, Cluster cluster) throws NacosException {    Service service = getService(namespaceId, serviceName);    if (service == null) {
Loggers.SRV_LOG.info("creating empty service {}:{}", namespaceId, serviceName); service = new Service(); service.setName(serviceName); service.setNamespaceId(namespaceId); service.setGroupName(NamingUtils.getGroupName(serviceName)); // now validate the service. if failed, exception will be thrown service.setLastModifiedMillis(System.currentTimeMillis()); service.recalculateChecksum(); if (cluster != null) { cluster.setService(service); service.getClusterMap().put(cluster.getName(), cluster); } service.validate();
putServiceAndInit(service); if (!local) { addOrReplaceService(service); } }}
复制代码


  1. 根据 namespaceId 和 serviceName 从缓存中获取 Service 实例

  2. 如果没有,创建并调用 putServiceAndInit()保存到缓存中。


putServiceAndInit 方法:


private void putServiceAndInit(Service service) throws NacosException {    putService(service);    service.init();    consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service);    consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service);    Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJSON());}
复制代码


  1. 通过 putService 方法将服务缓存到内存

  2. service.init();建立心跳检测机制,通过定时任务不断检测当前服务下所有实例最后发送心跳包的时间。如果超时,则设置 healthy 为 false 表示服务不健康,并发送服务变更事件。

  3. consistencyService.listen 实现数据一致性的监听

总结:

Nacos 提供了 SDK 和 Open API 的形式实现服务注册,两种方式本质都是一样的


服务注册对外提供的服务接口请求地址为 nacos/v1/ns/instance


服务注册过程:


  1. nacos 客户端通过 Open API 的形式发送服务注册请求

  2. 服务端收到请求:

  3. 构建一个 Service 对象保存到 Map 集合中

  4. 使用定时任务对当前服务下的所有实例建立心跳检测机制。

  5. 基于数据一致性协议将服务数据进行同步。nacos 的服务注册对我们很重要,我们要理解其中的原理和注册流程,然后分析看源码,从而更好的理解 nacos 是怎么实现服务的注册的,这样我们才能理解透彻 nacos 的运作机制,以后在我们工作中遇到什么问题,我们能够及时排查,快速定位,这样我们才能在工作和学习中更好的提高效率完成任务。你觉得这篇文章不错的话,请留言点赞评论~~

发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2020.02.29 加入

公众号《盼盼小课堂》,多平台优质博主

评论

发布
暂无评论
nacos注册中心之服务注册_7月月更_周杰伦本人_InfoQ写作社区