SpringCloud Consul功能介绍及其Raft算法原理

一、Consul 简介

Consul 为一款包含服务注册与发现、分布式一致性协议实现、健康检查、Key/Value存储、多数据中心方案 一体化的注册中心工具。

二、主要功能

  • 服务注册与发现

添加依赖,在yml文件中服务注册配置之后将服务启动后将会注册到consul注册中心上:

spring:
  application:
    name: service-product
  #consul 信息配置
  cloud:
    consul:
      host: 172.18.58.92 #consul注册中心的ip地址
      port: 8500 #consul注册中心端口
      discovery:
        register: true #是否需要注册
        instance-id: ${spring.application.name}-1 #实例id(唯一标志)
        service-name: ${spring.application.name} #服务的名称
        prefer-ip-address: true #开启ip地址注册
        ip-address: ${spring.cloud.client.ip-address} #当前服务的请求ip
        port: ${server.port} #服务的请求端口

可以通过 DNS 或 HTTP 的方式获取服务信息。

服务列表查询(get): http://192.168.17.128:8500/v1/catalog/services

服务详情查询(get):http://192.168.17.128:8500/v1/catalog/service/servicename

服务注册(put): http://192.168.17.128:8500/v1/catalog/register

{
	"Datacenter":"wuhan",
	"Node":"node-1",
	"Address":"172.18.58.92",
	"Service":{
		"ID":"test-service-id",
		"Service":"test-service",
		"tags":["master","v1"],
		"Address":"172.18.58.92",
		"Port":9001
	}
}

更多参考:https://www.consul.io/api-docs/index

  • 支持Ribbon 客户端负载均衡

借助给RestTemplate 添加 @Loadbalance 注解,可以在调用远程服务时使用服务名称来代替服务ip端口信息。

@Configuration
public class ApplicationContextConfig {

    @LoadBalanced
    @Bean
    public RestTemplate getRestTemplate(){
        return  new RestTemplate();
    }
}
@RestController
public class OrderController {
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/consumer/product/get/{id}")
    public CommonResult<Payment> getProduct(@PathVariable("id") Long id){
        return  restTemplate.getForObject("http://service-product/product/get/"+id,CommonResult.class);
    }
}
  • 分布式一致性协议实现

Consul的一致性协议实现主要依靠Raft算法进行选举以及选举后的数据同步来实现,文章下部分将对该算法进行详细描述。

  • 健康检查

Consul的健康检查是啥?做了什么,解决了什么,待补充

  • Key/Value 存储

新增数据:

查询数据:(查询全部、查询单条)

修改数据:

删除数据:

  • 多数据中心

多数据中心之间数据(服务数据、KV存储数据)不会同步,但是调用服务在当前中心没有的话,会找到对应的中心并进行跨中心调用并返回结果。

三、Raft算法介绍

节点的三种角色:当选人(Leader)、候选人(candidate)、跟随者(follower )。

在Raft中,有两个超时设置控制着选举过程,

1,选举超时时间(election timeout):一个节点从跟随者变成候选人的时间,这个时间为150ms到300ms之间的一个随机值。

2,心跳发送间隔时间(heartbeat timeout)。

选举算法流程:

0,系统初始三台节点都为跟随者(follower),并且当前轮数(term)为0。

1,当随机数超时时间最小的节点在选举超时时间之后,该节点第一个从跟随者(follower ) 变为候选人(candidate)。变更为候选人的节点的轮数加一(term=1),并且给自己投递一票,并且给其他节点发送投票请求信息。

 

2,当接受者在他们的节点在他们的轮数(term=0)的轮次内没有进行投过票,他们将会投票给提出投给自己票的候选者Node A,并且重新开始自身的超时时间(150ms-300ms),以及将自身的轮数也加一(term=1)。

4,一旦候选者在接收到了超过半数的选票后,则当选为Leader。当选为Leader的节点向其他节点发送 心跳 消息。并且这些消息以 心跳超时时间(heartbeat timeout)间隔发送给其他节点

跟随者在接收到消息后,会对该消息进行反馈回复。并且在每次接收到心跳消息后其重置自身的选举超时时间,从0开始计时,在随机的时间内接收到新的心跳请求,再继续重新计时。

系统将在当前状态中持续运行。直到某一台follower 在心跳时间内没有接收到心跳请求,变成了一个candidate 候选者。

场景1(此时Leader挂掉了):

1,当两台节点在接收到心跳请求后,开始新的计时。节点B的随机选举超时时间为160ms,节点C的随机选举超时时间为280ms。

2,由于在接收到上次心跳请求后,Leader节点挂掉了。节点B第一个先到达了自身的选举超时时间。由于该时间内没有收到心跳请求,节点B将自身变更为候选人,并投给自己一票,并将自身轮数term+1 变为 2,并发送给其他节点发送投票请求。

3,节点C收到投票请求后,投票给B,并将自身的轮数term+1 = 2。节点B收到了C的投票,以及自身的投票获得了半数以上(存活的节点一半以上的数)的投票,当选为新的Leader(term=2的Leader)。并且开始持续向其他节点发送心跳请求(包括挂掉的上一届(term=1)Leader)。由于新的Leader需要获得半数以上的投票,所以每次选举只能选出一个Leader.

 

场景2(当两个节点同时变为候选人时,分裂投票出现):

四个节点中,两个节点同时变为了候选人(B、D),并且他们向其他节点发送的投票请求,都分别先到达了一个跟随者(B->A,D->C)。

A和C 在接收到各自的第一个投票请求后,将票投递给了提出者。后面接收的请求本轮将不再投票。

此时B和C 各取得了两张投票。这是由于票数已经不能区分高低

节点将根据自身的选举超时时间再次发起投票。第一个变为候选人的将再次发送投票请求(并且term+1。自身票数记为1,自己投了自己一票),其他节点接收到投票请求后,term+1。重置选举超时时间,投票给候选人。直到选出一个Leader.

 

  • 选举过程(以五台举例)

step1:当分别启动五台单机的consul节点,并指定其正常运行的集群中最少正常节点数量为3。

step2:启动完成后,没太节点都是相互独立的节点,我们对节点1执行 consul join xx.xx.x.xx(节点5的ip),此时节点1和节点5将组成集群,但是当前集群数量2小于第一步中设置最小运行节点数3,所以集群仍不能提供服务。

step3:我们在节点2上执行 consul join xx.xx.x.xx(节点5的ip),此时 节点1、2、5将组成集群,并且当前集群节点数量3 大于等于 启动设置的最小运行节点数3 。当前三台节点将开始进行选举。

step4:三台节点目前角色都为选举者,根据上面的选举过程,将产生一个Leader.

step5:后续的节点4 和 5 在加入集群时发现已经有了Leader将直接变为跟随者。

  • 数据同步过程

1,一个client发送了一个 改变数据请求到Leader,更改将添加到领导者的日志中

2,主节点将在下次心跳请求中传递改变信息,Leader在收到大多数的反馈后,将进行提交。并且对客户端做一个反馈。

3,客户端发送了一个+2的操作请求给Leader,Leader 将+2 操作发给每个节点,并收到后自身也+2 操作。操作完成反馈给client。

分区情况下的同步,在开始为一个网络环境下的5个节点,由于网络故障,集群被分割成了两部分,相互不能通讯。在其他节点较多的没有主节点的节点将term加一,并进行重新选举。

发送到B上的数据更改由于没能同步到大多数的节点上,所以该条请求未能进行提交处理。另外一部分节点由于节点数较多,收到的数据操作请求同步到了大多数节点上,故可以被提交

 

网络修复好之后,两个节点都想集群中节点发送心跳,由于上面部分的三个节点的term较高,为最新的集群状态。并且都跟随新的Leader。老的Leader将退出成为跟随者。节点B和A回滚未提交的数据请求,整个节点数据将以term高的集群数据为准。

 

四、与Eureka对比

CAP: 一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)

1,一致性

Consul与Zookeeper 一样,遵循的CP 强一致性 。使用Consul注册服务时,需要等大多数节点都写入成功才认为注册成功,相比Eureka的一个节点处理了就返回注册成功相比,Consul 服务注册会慢一些。当主节点挂掉,重新选举时间段内,不能对外提供服务,保证了强一致性,牺牲了可用性。

Eureka 保证高可用和最终一致性(AP)。服务注册相对较快,因为不需要等其他节点都数据同步上。但有可能同步不成功,其他节点该服务信息不可用,但是有问题节点找不到数据,会从其他节点获取到。

2,开发语言

Consul 基于Go语言开发,安装即用。Eureka 为Servlet程序,运行在Servlet容器中。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值