SpringCloud之Consul

Consul简介

  • 注册中心(不仅仅是注册中心)
  • 一致性协议采用 Raft 算法,用来保证服务的高可用和一致性,实际是CP的模型,并且提供了可配置的3种一致性模式(stale、consistent、default)
  • 具有键值对存储功能
  • 允许 HTTP 和 DNS 协议调用 API,执行一些业务操作,比如存储键值对(./consul kv get user/config/connections , http://localhost:8500/v1/kv/?recurse 查看所有键值对)
  • 自带web界面来查看和执行一些操作
  • 支持多数据中心
  • Consul 丰富的健康检查(http接口、脚本、tcp等形式定时任务检测)
  • 支持 ACL 访问控制.
  • 由 HashiCorp 公司用 Go 语言开发
  • 使用 GOSSIP 协议管理成员和广播消息

Consul 、Eureka、Zookeeper 比拼

  1. Eureka最单纯,定位就是注册中心,在CAP模型里面,追求的是AP,牺牲一致性,追求服务的高可用。Eureka集群模式中,大家地位平等,自己监听到了新的注册应用,该Eureka节点会通过RPC相互转告。默认开启保护功能,即使是超时的注册服务,也不会从Eureka中注销。
  2. Consul扩展了很多功能,除了注册中心、也支持做配置中心、键值对存储、丰富形式的健康检查、多数据中心、Acl控制、日志快照生成等功能
  3. Zookeeper自己的定位是分布式协调器,也扩展了很多的功能:分布式锁、Watcher通知机制、分布式下的队列管理、键值对存储
  4. Consul追求CP,一致性通过Raft算法实现的,典型的Paxos的变种算法,Leader、follower、候选者角色,选举时主要看日志是否最新来控制的,但是有3种一致性模式来满足不同的业务场景。
  5. Zookeeper追求CP,一致性通过Zab协议实现的,也是典型的Paxos的变种算法,角色有Leader、Follower、Observer,选举的时候都是半数通过,选举时主要是基于zxid来控制的。
  6. Eureka和Consul都自带UI界面来支持管理功能,ZK不支持
  7. 在事务请求时或者网络抖动时,Eureka都是最快的,因为ZK和Consul都为了确保一致性,会涉及投票半数通过这个等待过程。在网络抖动的时候,ZK和Consul会重新选举,功能暂时不可用,而Eureka不存在
  8. 健康检查失效节点剔除功能,Consul默认是通过http接口,也就是Provider的actuator/health来实现的,超时会剔除故障Provider,而Eureka通过自身的心跳功能实现Provider的健康检查,不依赖actuator

CAP理论

  • C数据一致性,不管在任何时候,从集群中任意一个节点读取到的数据应该一样,
  • A高可用性,不会因为某个结点的故障而导致整个集群等待不可用
  • P分区容错性,集群的节点之间的通讯,可能因为某些原因,比如网络,比如某个结点宕机,也要确保整个集群的功能可用
    如果此时要保持整个集群可用,因为P是无法避免的,所以一般CAP理论,要么选择CP,要么选择AP,无法做到兼顾。
    实际上Zookeeper和Consul实现的强一致性也不是100%的一致性,只需要半数机器Ack Purpose后,Leader就认为这个事务成立,commit本地日志后,就响应客户端了,同时会通知其他Follower Commit。

基本原理

  1. Consul集群下,Consul Leader和Consul Follower之间通过定时发送心跳,检测各个节点间的网络通畅,从而确保数据一致。Follower节点在超时还未接收到心跳,就会发起选举。
  2. Consul和provider、Consumer之间都保持默认10秒间隔的心跳,从而保证注册在Consul的Provider仍然可用,以及Consumer手中拿到的provider-list是最新的
  3. Consul中所有的节点分为:Client模式和Server模式(也包括Server模式节点刚启动时的BootStrap模式)(所有的节点也被称为Agent),Server模式下的节点,参与一致性投票、存储和追加日志、可能会直接处理查询的请求(stale模式下),而Client负责健康检查及转发数据请求到Server;

Consul注册中心的原理

  1. 当Provider 启动的时候,会向 Consul 发送一个 post 请求,告诉 Consul 自己的 IP 和 Port
  2. Consul 接收到 Provider 的注册后,每隔10s(默认)会向Provider发送一个健康检查的请求,检验Provider是否健康
  3. 当 Consumer 发送 GET 方式请求 /api/address 到 Provider 时,会先从 Consul 中拿到一个存储服务 IP 和 Port 的临时表,从表中拿到 Provider 的 IP 和 Port 后再发送 GET 方式请求 /api/address
  4. 该临时表每隔10s会更新,只包含有通过了健康检查的 Provider

Consul的一致性

https://blog.csdn.net/u012422829/article/details/77803799

读取的请求

Consul支持3种模式的一致性选择:stale模式、consistent模式、default模式

  1. stale模式和Eureka有点类似,在执行读取操作的时候,所有的节点的地位是一样,都可以直接返回给客户端,当前节点的数据,虽然可能此时该节点的数据不是最新的,但是读取的速度最快
  2. consistent模式是强一致性模式,所有的读取请求都需要转发给Leader节点,Leader节点每次做读和写操作时都要与法定个数的节点去确认自己仍然是leader。 牺牲读的速度,保障了强一致性
  3. default模式,因为leader节点是定时的发起心跳,来判断自己和各个节点的连接状态,那么在这个心跳的空闲期,它会以为自己还是Leader,所有的读取请求都需要转发给Leader节点,Leader节点无需和其它节点确认自己是否是Leader节点,直接返回结果,但是这种模式是对读取速度和一致性的一种取舍,牺牲了某些情况下的强一致性,以换取更高的读取速度。比如:leader节点与别的节点被分隔,即发生所谓“脑裂”现象,那么会有一个新的leader节点被选举出来。旧的leader节点将不能提交任何新的log entry, 但是如果它提供了对数据的读取,那么客户端读到的这些值可能是过期的。

事务的请求

日志复制(类似于ZAB协议):Raft中,所有的事务操作都需要交给Leader来处理,leader通过强制followers复制自己的logs来处理不一致。这意味着,在follower中logs冲突的entries将会被leader logs中的覆写。

  1. 任意节点收到客户端发起的事务请求的时候,会把该事务转发给Leader服务器
  2. Leader先把该日志追加到本地的Log中,然后把该Entry同步给其他Follower
  3. Follower接收到日志后记录日志然后向Leader发送ACK
  4. 当Leader收到大多数(n/2)+1 Follower的ACK信息后将该日志设置为已提交并追加到本地磁盘中,通知客户端
  5. 并在下个heartbeat中Leader将通知所有的Follower将该日志存储在自己的本地磁盘中

Consul的选举Leader

https://www.consul.io/docs/guides/leader-election.html
Consul里面有一个标识leader角色的 K/V键值对,key的话类似于 service/<service name>/leader,value记录了该leader对应的sessionid

  1. 结合Raft协议,当一个follower和leader的心跳超时了,晋升为Candidate,会发起一次选举
  2. 该节点(可能同时有多个节点都会发起这个操作)会创建一个session,创建成功后会获得一个sessionid
  3. 然后发起尝试修改leader键的值为自己,就是尝试成为leader
  4. 这个时候触发Raft选举,如果通过半数通过的话,成为新的leader,leader键值对的value就是该server的sessionid
  5. 非Leader的节点,会通过读取这个键值对来确定谁是leader,并且把事务请求(可能也包括读取请求)转发给当前任期的leader

Raft选举Leader

https://www.consul.io/docs/internals/consensus.html
Raft状态下所有的节点有3种状态:Leader、Follower、Candidate。
有一个任期的概念,类似于朝代,也类似于计数器,每个server各自都有一个,老Leader故障时,被一个follower察觉后,该follower会自增自己的当前任期,发起投票。

触发条件:

  1. 一般情况下,追随者接到领导者的心跳时,把自己的ElectionTimeout清零,不会触发;
  2. 如果领导者故障,追随者的ElectionTimeout超时发生时,会变成候选者,触发领导人选取;

候选操作过程:
追随者自增当前任期,转换为Candidate,对自己投票,并发起RequestVote RPC,等待下面三种情形发生;

  1. 自己成功:获得超过半数服务器的投票,赢得选举,成为领导者;
  2. 别人成功:另一台服务器赢得选举,并接收到对应的心跳,成为追随者;
  3. 都失败:选举超时,没有任何一台服务器赢得选举,自增当前任期,重新发起选举;

选举限制:投票阻止没有全部日志条目的服务器赢得选举

  1. 比较数据,如果投票者的日志比候选人的新,拒绝投票请求;这意味着要赢得选举,候选者的日志至少和大多数服务器的日志一样新,那么它一定包含全部的已经提交的日志条目。
  2. 比较任期,投票人会拒绝任何任期小于当前的RPC请求,包括添加日志请求和发起投票的RPR请求,任期小的节点数据肯定是过时的
  3. 先到先得,一个server收到其它候选者的vote投票,因为在一个任期里,多个候选者都发觉Leader挂了,几乎同时向该server发送vote投票,所以server在一个term肯定只能投一个,而且投给最先发起的那个

注意事项:

  1. 候选者等待投票时,可能会接收到来自其它声明为领导人的的AppendEntries RPC。如果该领导人的任期(RPC中有)比当前候选人的当前任期要大,则候选人认为该领导人合法,并转换成追随者;如果RPC中的任期小于候选人的当前任期,则候选人拒绝此次RPC,继续保持候选人状态;
  2. 候选人既没有赢得选举也没有输掉选举:如果许多追随者在同一时刻都成为了候选人,选票会被分散,可能没有候选人能获得大多数的选票。当这种情形发生时,每一个候选人都会超时,并且通过自增任期号和发起另一轮 RequestVote RPC 来开始新的选举。然而,如果没有其它手段来分配选票的话,这种情形可能会无限的重复下去。所以Raft使用的随机的选举超时时间(150~300ms之间),来避免这种情况发生。

解决的现实情况:

  1. 老的Leader真挂了,会触发选举,最终会让数据最新的节点成为新的leader
  2. 如果一个follower自己和leader的网络有延迟,导致没有接收到心跳,误发起投票,但是数据不是最新,选举肯定失败

Raft其它

  1. Log:所有的写操作通过一系列有序的Entry日志组成,数据的一致性通过,拷贝日志文件来实现

  2. 投票有效人数:也就是执行一个事务操作,需要过半的Server ACK后才行

  3. Leader,在任意时间节点,都只有一个Node是Leader地位,Leader负责添加新的Log,以及发起Propose,收集ACK和发起Commit

  4. Consul在工作流程中RPC有三种:

  • RequestVote RPC:候选人在选举期间发起
  • AppendEntries RPC:领导人发起的一种心跳机制,复制日志也在该命令中完成
  • InstallSnapshot RPC: 领导者使用该RPC来发送快照给太落后的追随者。
  1. 为了提升选举的速度和写的速度,Consul节点分为Client模式和Server模式。只有以server模式运行的Consul节点,才会被认为是Raft节点集的一部分。所有的client节点会把收到的请求转发到server节点中。这么设计的原因主要是出于性能方面的考虑:节点集中的个数越多,那么法定个数的值也就越大,这会导致leader节点可能需要等待数百个follower节点对一条log entry的ack信息。

  2. 如果follower出现了问题,以及问题后的重连

  • leader后续发送给掉线节点的 RequestVote和AppendEntries的所有RCP都会失败,Raft算法中处理这类失败就是简单的Leader无限发起重试
  • 问题服务器重新可用,也会重试失败之前的那个操作,如果问题服务器完成了一个RPC,但是在响应Leader前崩溃了(比如ACK某条日志),那么当他再次可用的时候还会收到相同的RPC请求,此时接收服务器(leader)负责检查,比如如果收到了已经包含该条日志的RPC请求,可以直接忽略这个请求,确保对系统是无害的。
  1. raft支持日志压缩成快照,来快速同步数据,降低存储的压力,与Raft其它操作Leader-Based不同,snapshot是由各个节点独立生成的。除了日志压缩这一个作用之外,snapshot还可以用于同步状态:slow-follower以及new-server,Raft使用InstallSnapshot RPC完成该过程

consul 的键值对功能

# 往consul里面 key为 user/config/connections的 value值为 5
./consul kv put user/config/connections 5
# get 值
./consul kv get user/config/connections 

Consul 之健康检查功能

Consul支持多种方式的健康检查功能:脚本、http接口、tcp等等
集成SpringCloud的项目中,一般都是通过http接口,定时调用Provider的actuator的/health接口来实现的,支持自定义配置healthCheckInterval时间,而且过期的应用会从Consul的服务列表中删除掉。

  1. 定时任务的脚本(我试了shell失败了),根据脚本执行的返回码 0 passing 1 warning 其它都是failing,执行成功返回,执行失败
  2. http接口的返回码,200,
    HTTP GET http://G5CG72855HGE.logon.ds.ge.com:8501/actuator/health: 200 Output: {"status":"UP"}

安装和启动

下载之后,进入到 C:\huangzs\software 目录下: ./consul agent -dev
然后访问 http://localhost:8500

Consul的注册中心的使用

  1. 先启动consul服务
  2. Consumer和Provider添加两个依赖jar包
  • spring-boot-starter-actuator 健康检查依赖于此包。
  • spring-cloud-starter-consul-discovery Spring Cloud Consul 的支持。
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    </dependency>

  1. 配置文件
spring.application.name=spring-cloud-consul-producer
server.port=8501
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.serviceName=service-producer
  1. Provider的启动类添加@EnableDiscoveryClient, Consumer的启动类不需要配置这个,因为没必要暴露自己的服务,Eureka也一样

参考资料

http://www.ityouknow.com/springcloud/2018/07/20/spring-cloud-consul.html

Consul官方文档
https://www.consul.io/docs/guides/leader-election.html

Consul中文文档
https://blog.csdn.net/y435242634/article/details/78957447

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • 可进入我的博客查看原文。 Raft 算法是可以用来替代 Paxos 算法的分布式一致性算法,而且 raft 算法比...
    Jeffbond阅读 13,296评论 4 91
  • 寻找一种易于理解的一致性算法(扩展版) 摘要 Raft 是一种为了管理复制日志的一致性算法。它提供了和 Paxos...
    yflau阅读 942评论 0 1
  • 寻找一种易于理解的一致性算法(扩展版) 摘要 Raft 是一种为了管理复制日志的一致性算法。它提供了和 Paxos...
    糖果果老师阅读 1,242评论 0 4
  • 寻找一种易于理解的一致性算法(扩展版) 摘要 Raft 是一种为了管理复制日志的一致性算法。它提供了和 Paxos...
    枝叶君阅读 2,627评论 0 15
  • 有人说,我是名可爱的女孩子; 有人说,我是名漂亮的女孩子; 有人说,我是名坚强的女孩子; 有人说,我是名女汉子.....
    暮夏_阅读 461评论 0 0