Nacos config原理

一、Nacos Config与Spring Cloud Config原理对比

  说到Nacos Config配置中心的原理,就不得不提一下Spring Cloud Config配置中心的原理,二者是如此的相似,但却也有着很多不同的特点。

  1、Spring Cloud Config原理

      

    (1)提交配置触发post请求给server端的bus/refresh接口

    (2)server端接收到请求并发送给Spring Cloud Bus总线

    (3)pring Cloud bus接到消息并通知给其它连接到总线的客户端

    (4)其它客户端接收到通知,请求Server端获取最新配置

    (5)全部客户端均获取到最新的配置 

  2、Nacos Config工作原理

    

 

    (1)客户端发起长轮训请求

    (2)服务端收到请求以后,先比较服务端缓存中的数据是否相同

      如果不同,则直接返回

      如果相同,则通过schedule延迟30s之后再执行比较。3. 为了保证当服务端在30s之内发生数据变化能够及时通知给客户端,服务端采用事件订阅的方式来监听服务端本地数据变化的事件,一旦收到事件,则触发通知把结果写回到客户端,完成一次数据的推送

    (3)为了保证当服务端在30s之内发生数据变化能够及时通知给客户端,服务端采用事件订阅的方式来监听服务端本地数据变化的事件,一旦收到事件,则触发通知把结果写回到客户端,完成一次数据的推送

  3、两种配置中心对比

    Nacos Config 无需消息总线系统,系统搭建成本与复杂度比 SpringCloud Config 低很多。

    Nacos Config 不会一窝蜂向配置中心索要配置信息,Nacos Config是定点更新。

    Nacos Config 有远程配置更新后,会自动更新到 client。其采用了长轮询 Pull 模型。而Spring Cloud Config 则需要 client 提交请求。 

二、Nacos Config中的长轮询Pull模型

  配置中心Server和客户端Client实现配置的动态感知一般无外乎两种办法:

    一种是Client发起,叫pull模式

    一种是Server发起,叫push模式

  长轮询中Push模式和Pull模式的对比:

    若使用 Push 模型,需要在 Server 与 Client 间通过心跳机制维护一个长连接。这个长连接的维护成本是比较高的。其适合于 Client 数量不多,且 Server 端数据变化较频繁的场景。优点:数据更新很及时。

    若使用 Pull 模型,其无需维护长连接【29.5s】,但其实时性不好。

  Nacos 采用的是长轮询机制的 Pull 模型,但不单纯是Pull模型。是一个HttpPost的长轮询,过期时间默认是30S。

  Nacos 长轮询 Pull 模型融合了 Push 与 Pull 模型的优势。Client 仍定时发起 Pull 请求,查看 Server 微服务框架 端数据是否更新。若发生了更新,则 Server 立即将更新数据以响应的形式发送给 Client 端;若没有发生更新,Server 端并不立即向 Client 返回响应,而是临时性的保持住这个连接一段时间【29.5s】。若在此时间段内,Server 端数据发生了变更,则立即将变更数据返回给 Client【这里是动态感知的】。若仍未发生变更,则放弃这个连接。等待着下一次 Client 的 Pull 请求。

  长轮询 Pull 模型,是 Push 与 Pull 模型的整合,既降低了 Push 模型中长连接的维护问题,又降低了 Push 模型实时性较低的问题。 

      

 

三、Nacos采用的Raft算法及集群选举

  1、CAP

    目前应用的比较多的注册中心,Eureka 是 AP 的,Zookeeper 是 CP 的。默认情况下,Nacos Discovery 集群是 AP的。但其也支持 CP 模式,需要进行转换。若要转换为 CP 的,可以提交如下 PUT 请求,完成 AP 到 CP 的转换。

http://localhost:8848/nacos/v1/ns/operator/switches?entry=ServerMode&value=CP

 

  2、Raft算法

    Nacos Discovery 集群为了保证集群中数据的一致性,其采用了 Raft 算法。这是一种通过对日志进行管理来达到一致性的算法。Raft 通过选举 Leader 并由 Leader 节点负责管理日志复制来实现各个节点间数据的一致性。

    Raft算法是一个最终一致性的算法,不是强一致性算法。Raft 算法动画演示:http://thesecretlivesofdata.com/raft/

  3、Raft Leader选举

    在 Raft 中,节点有三种角色:

      Leader【主】:唯一负责处理客户端写请求的节点;也可以处理客户端读请求;同时负责日志复制工作

      Candidate【候选人】:Leader 选举的候选人,其可能会成为 Leader

      Follower【从】:可以处理客户端读请求;负责同步来自于 Leader 的日志;当接收到其它Cadidate 的投票请求后可以进行投票;当发现 Leader 挂了,其会转变为 Candidate 发起Leader 选举

    除了三种角色外,还有一个iterm,可以将其看为一个编号,在Leader选举中发挥作用.

    leader选举流程:

        

  (1)成为候选人

    若 follower 在心跳超时范围内没有接收到来自于 leader 的心跳,则认为 leader 挂了。此时其首先会使其本地 term 增一。然后 follower 会完成以下步骤:

      a、此时若接收到了其它 candidate 的投票请求,会根据以下两种情况来判断是否投票:

        如果在我当前 term 内,且我的选票还没有投出去,则会投票给该节点。(发来投票请求候选人candidate 的节点 term 不能小于我的 term)

        如果当前Follower节点接收到多个 candidate 的请求,当前节点将采取,先到先得的方式投票

      b、由 follower 转变为 candidate,本地 term 加一之前尚未投票,则向自己投一票,然后向其它节点发出投票请求,然后等待响应。响应结果可能有三种情况:

        收到过半选票,成为新的 leader。然后会将消息广播给所有其它节点,以告诉大家我是新的 Leader 了,其中就包含新的 term

        接收到别的 candidate 发来的新 leader 通知,比较了新 leader 的 term 并不比的 term小,则自己转变为 follower

        经过一段时间后,没有收到过半选票,也没有收到新 leader 通知,则重新发出选举

  (2) 票数相同怎么处理

    若在选举过程中出现了各个 candidate 票数相同的情况,是无法选举出 Leader 的。当出现了这种情况时,其采用了 randomized election timeouts 策略来解决这个问题。其会让这些candidate 重新发起选举,只不过发起时间不同:各个 candidate的选举发起时间是在一个给定范围内等待随机时长 timeout 之后开始的。timeout 较小的会先开始选举,一般情况下其会优先获取到过半选票成为新的leader。

四、Raft 算法下集群脑裂情况

    Raft 集群存在脑裂问题。在多机房部署中,由于网络连接问题,很容易形成多个分区。而多分区的形成,很容易产生脑裂,从而导致数据不一致。由于三机房部署的容灾能力最强,所以生产环境下,三机房部署是最为常见的。下面以三机房部署为例进行分析,根据机房断网情况,可以分为五种情况:

  (1)情况一:不确定

        

     这种情况下,B 机房中的主机是感知不到 Leader 的存在的,所以 B 机房中的主机会发起新一轮的 Leader 选举。由于 B 机房与 C 机房是相连的,虽然 C 机房中的Follower 能够感知到 A 机房中的 Leader,但由于其接收到了更大 term 的投票请求,所以 C 机房的 Follower也就放弃了 A 机房中的 Leader,参与了新 Leader 的选举。

    若新 Leader 出现在 B 机房,A 机房是感知不到新 Leader 的诞生的,其不会自动下课,所以会形成脑裂。但由于 A 机房 Leader 处理的写操作请求无法获取到过半响应,所以无法完成写操作。但 B 机房 Leader 的写操作处理是可以获取到过半响应的,所以可以完成写操作。故,A 机房与 B、C 机房中出现脑裂,且形成了数据的不一致。

    若新 Leader 出现在 C 机房,A 机房中的 Leader 则会自动下课,所以不会形成脑裂。 

  (2)情况二:会脑裂

        

 

 

    这种情况与情况一基本是一样的。

  (3)情况三:不会脑裂
 
       

     A、C 可以正常对外提供服务,但 B 无法选举出新的 Leader,无法提供服务,没有形成脑裂。

  (4)情况四:不会脑裂

        

 

    A、B、C 均可以对外提供服务,不受影响。

  (5)情况五:不会脑裂

        

     A 机房无法处理写操作请求,但可以对外提供读服务。B、C 机房由于失去了Leader,均会发起选举,但由于均无法获取过半支持,所以均无法选举出新的Leader。 

五、Leader宕机的四种情况处理

        

   client发送请求到Nacos Config集群,Leader会将请求同步到Follower,同步完成后,才会返回客户端成功,但是存在各种情况,但是总的来说就是只有全部同步完成才会返回客户端成功。

  (1) 情况1:请求到达前Leader挂了

    client 发送写操作请求到达 Leader 之前 Leader 就挂了。因为请求还没有到达集群,所以这个请求对于集群来说就没有存在过,对集群数据的一致性没有任何影响。Leader 挂了之后,会选举产生新的 Leader。由于 StaleLeader 并未向 client 发送成功处理响应,所以 client 会重新发送该写操作请求。

  (2) 情况2:未开始同步数据前Leader挂了

    client 发送写操作请求给 Leader,请求到达 Leader 后,Leader 还没有开始向Followers复制数据 Leader 就挂了。这时集群会选举产生新的 Leader,前任Leader 重启后会作为Follower 重新加入集群,并同步新 Leader 中的数据以保证数据一致性。之前接收到 client 的数据被丢弃。由于前任 Leader 并未向 client 发送成功处理响应,所以 client 会重新发送该写操作请求。

  (3) 情况3:同步完部分后Leader挂了

    client 发送写操作请求给 Leader,Leader 接收完数据后开始向 Follower 复制数据。在部分 Follower 复制完后 Leader 挂了(可能过半也可能不过半)。由于Leader 挂了,就会发起新的 Leader 选举。

      若 Leader 产生于已经复制完日志的 Follower,其会继续将前面接收到的写操作请求完成,并向 client 进行响应。

      若 Leader 产生于尚未复制日志的 Follower,那么原来已经复制过日志的Follower 则会将这个没有完成的日志放弃。由于 client 没有接收到响应,所以client 会重新发送该写操作请求。

  (4) 情况4:apply通知发出后Leader挂了

    client 发送写操作请求给 Leader,Leader 接收完数据后开始向 Follower 复制数据。Leader成功接收到过半 Follower 复制完毕的响应后,Leader 将日志写入到状态机。此时 Leader 向Follower 发送 apply 通知。在发送通知的同时,也会向 client发出响应。此时 leader 挂了。由于 前任 Leader 已经向 client 发送成功接收响应,且 apply 通知已经发出,说明这个写操作请求已经被 server 成功处理。 

  



 

posted @ 2021-10-14 21:02  李聪龙  阅读(914)  评论(0编辑  收藏  举报