Nacos服务注册中心底层实现原理

1.x版本是通过Http协议来进行服务注册的2.x由于客户端与服务端的通信改成了gRPC长连接,所以改成通过gRPC长连接来注册2.x比1.x多个Redo操作,当注册的服务实例是临时实例是,出现网络异常,连接重新建立之后,客户端需要将服务注册、服务订阅之类的操作进行重做这里你可能会有个疑问既然2.x有Redo机制保证客户端与服务端通信正常之后重新注册,那么1.x有类似的这种Redo机制么?当然也会有,接下往下看。心跳机制仅仅针对临时实例而言。
摘要由CSDN通过智能技术生成

今天来讲一讲Nacos作为服务注册中心底层的实现原理

不知你是否跟我一样,在使用Nacos时有以下几点疑问:

  • 临时实例和永久实例是什么?有什么区别?
  • 服务实例是如何注册到服务端的?
  • 服务实例和服务端之间是如何保活的?
  • 服务订阅是如何实现的?
  • 集群间数据是如何同步的?CP还是AP?
  • Nacos的数据模型是什么样的?

本文就通过探讨上述问题来探秘Nacos服务注册中心核心的底层实现原理。

虽然Nacos最新版本已经到了2.x版本,但是为了照顾那些还在用1.x版本的同学,所以本文我会同时去讲1.x版本和2.x版本的实现

观前提醒,本文又又又是一篇超长的干货,非常适合一键三连~~

临时实例和永久实例

临时实例和永久实例在Nacos中是一个非常非常重要的概念

之所以说它重要,主要是因为我在读源码的时候发现,临时实例和永久实例在底层的许多实现机制是完全不同的

临时实例

临时实例在注册到注册中心之后仅仅只保存在服务端内部一个缓存中,不会持久化到磁盘

这个服务端内部的缓存在注册中心届一般被称为服务注册表

当服务实例出现异常或者下线之后,就会把这个服务实例从服务注册表中剔除

永久实例

永久服务实例不仅仅会存在服务注册表中,同时也会被持久化到磁盘文件中

当服务实例出现异常或者下线,Nacos只会将服务实例的健康状态设置为不健康,并不会对将其从服务注册表中剔除

所以这个服务实例的信息你还是可以从注册中心看到,只不过处于不健康状态

这是就是两者最最最基本的区别

当然除了上述最基本的区别之外,两者还有很多其它的区别,接下来本文还会提到

这里你可能会有一个疑问

为什么Nacos要将服务实例分为临时实例和永久实例?

主要还是因为应用场景不同

临时实例就比较适合于业务服务,服务下线之后可以不需要在注册中心中查看到

永久实例就比较适合需要运维的服务,这种服务几乎是永久存在的,比如说MySQL、Redis等等

MySQL、Redis等服务实例可以通过SDK手动注册

对于这些服务,我们需要一直看到服务实例的状态,即使出现异常,也需要能够查看时实的状态

所以从这可以看出Nacos跟你印象中的注册中心不太一样,他不仅仅可以注册平时业务中的实例,还可以注册像MySQL、Redis这个服务实例的信息到注册中心

在SpringCloud环境底下,一般其实都是业务服务,所以默认注册服务实例都是临时实例

当然如果你想改成永久实例,可以通过下面这个配置项来完成

spring
  cloud:
    nacos:
      discovery:
        #ephemeral单词是临时的意思,设置成false,就是永久实例了
        ephemeral: false

这里还有一个小细节

在1.x版本中,一个服务中可以既有临时实例也有永久实例,服务实例是永久还是临时是由服务实例本身决定的

但是2.x版本中,一个服务中的所有实例要么都是临时的要么都是永久的,是由服务决定的,而不是具体的服务实例

所以在2.x可以说是临时服务永久服务

图片

为什么2.x把临时还是永久的属性由实例本身决定改成了由服务决定?

其实很简单,你想想,假设对一个MySQL服务来说,它的每个服务实例肯定都是永久的,不会出现一些是永久的,一些是临时的情况吧

所以临时还是永久的属性由服务本身决定其实就更加合理了

服务注册

作为一个服务注册中心,服务注册肯定是一个非常重要的功能

所谓的服务注册,就是通过注册中心提供的客户端SDK(或者是控制台)将服务本身的一些元信息,比如ip、端口等信息发送到注册中心服务端

服务端在接收到服务之后,会将服务的信息保存到前面提到的服务注册表中

1、1.x版本的实现

在Nacos在1.x版本的时候,服务注册是通过Http接口实现的

图片

代码如下

图片

整个逻辑比较简单,因为Nacos服务端本身就是用SpringBoot写的

但是在2.x版本的实现就比较复杂了

2、2.x版本的实现

2.1、通信协议的改变

2.x版本相比于1.x版本最主要的升级就是客户端和服务端通信协议的改变,由1.x版本的Http改成了2.x版本gRPC

gRPC是谷歌公司开发的一个高性能、开源和通用的RPC框架,Java版本的实现底层也是基于Netty来的

之所以改成了gRPC,主要是因为Http请求会频繁创建和销毁连接,白白浪费资源

所以在2.x版本之后,为了提升性能,就将通信协议改成了gRPC

根据官网显示,整体的效果还是很明显,相比于1.x版本,注册性能总体提升至少2倍

虽然通信方式改成了gRPC,但是2.x版本服务端依然保留了Http注册的接口,所以用1.x的Nacos SDK依然可以注册到2.x版本的服务端

2.2、具体的实现

Nacos客户端在启动的时候,会通过gRPC跟服务端建立长连接

图片

这个连接会一直存在,之后客户端与服务端所有的通信都是基于这个长连接来的

当客户端发起注册的时候,就会通过这个长连接,将服务实例的信息发送给服务端

服务端拿到服务实例,跟1.x一样,也会存到服务注册表

除了注册之外,当注册的是临时实例时,2.x还会将服务实例信息存储到客户端中的一个缓存中,供Redo操作

所谓的Redo操作,其实就是一个补偿机制,本质是个定时任务,默认每3s执行一次

这个定时任务作用是,当客户端与服务端重新建立连接时(因为一些异常原因导致连接断开)

<
  • 32
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Elivis Hu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值