Consul的架构

如下图所示:

 

通常情况下, 一个数据中心由client和server组成, 并且需要保证server相对较少, 因为server越多, server之间达成一致的速度越慢。

一个数据中心的所有agent都参与一个gossip协议。

Consul使用gossip协议来管理集群中的成员关系, 广播消息到集群中。所有的这些都是通过Serf库实现的, serf使用的gossip协议是SWIM(Scalable Weakly-consistent infection-style process group membership protocol).

 

client: 即以client模式启动的consul客户端, 通常情况下只是转发请求到server, 并且占用的资源极少。

server: 即以server模式启动的consul客户端。每个数据中心的所有server都是一个Raft peer set中的一员, 他们的职责通常包括选举出一个leader, 这个leader负责处理所有请求和事务。 作为一致性协议的一部分,事务会被转发到peer set中的所有成员。当一个非leader的server接收到一个RPC请求时, 它会转发请求到当前数据中心的leader。

 

Consul使用基于Paxos的Raft来提供一致性协议(consensus protocol),即CAP中的C。相比于Paxos, Raft拥有更少的状态, 并且算法也更容易理解。

Raft中有几个关键的概念:

Log : 在一个Raft系统中, 最基础的工作单位就是一条log记录。 因此一致性的问题也就成了log的一致性问题。 Log是有序的, 包含了集群(cluster)中的所有的变化:添加节点, 添加服务, 增加key-value键值对等等。当所有的集群成员都同意log中的记录以及顺序时, 这个log被认为是一致的。

FSM: 无限状态机, 一个无限状态机就是有限状态机的集合,并且包含了它们之间转换的方法。当新的log被应用的时候, FSM被允许在状态之间进行转换。拥有相同顺序的所有log的应用程序必然最终会到达同一个状态。

Peer set: 一个peer set即使参与log备份的所有的成员。 从Consul的角度来说, 所有的server节点都参与到本地数据中心的peer set中。

Quorum: 一个quorum是一个peer set中的主要成员, 必须如果peer set大小为n,则quorum要求至少(n/2)+1个成员。如果一个集群中一个quorum数量的节点失败, 则这个集群就无法提供服务, 并且无法提交新的log。

Committed Entry: 当一个entry被持久化到一个quorum数量的节点上时, 这个log记录被认为是已提交, 并可以被应用到状态机。

Leader: 在任何时间, 一个peer set中只有一个节点可以成为leader, leader负责生成新的日志记录, 传播到follower中, 并且决定何时一个记录被认为是已提交。

 

一个Raft节点总共有三个状态:follower, candidate或者leader.

所有节点启动时是follower状态, 在这个状态,节点可以接收leader的日志记录并且参与Leader选举投票。当节点在一段时间没有接收到Leader的日志记录时, 节点会自动进入candidate状态。

在candidate状态中, 节点要求peer set中的其他成员投票, 如果投票超过一个quorum数量, 则会成为leader。

Leader必须接收新的日志记录并且传播到其他的follower中。如果请求不接受过期的数据, 则所有的查询请求必须由leader来响应。

 

Raft提供了一个机制, 可以快照保存当前的状态并且压缩日志 , 这样可以把保存的状态之前的所有日志移除到, 以节省空间, 这个是Raft自动完成的。Consul使用MemDB保存集群的状态, 而MemDB的一个优点就是可以在快照保存状态机的状态时依然接收新的事务。

 

 

Raft In Consul

刚开始时, 一个Consul server可以以"bootstrap"模式启动, 这个模式可以允许server自选为leader。 一旦leader确定, 其他的server就会加入到这个peer set中。

由于所有的节点都知道当前的Leader, 当RPC请求到达非leader server时,请求被转发leader。

如果这个请求时查询类型, 则leader基于状态机当前的状态生成结果;

如果这个请求时事务类型(transaction type), 意味着是更改状态, 则leader生成一个新的log记录, 并且通过Raft应用这条记录。

 

一致性模式

所有的修改请求都会经过Raft形成日志记录, 但是读请求却有更多的选项。Consul支持3种读一致性模式:

default: Raft通过leader租赁的方法, 保证在一个时间窗口内, leader的角色是不变的。

consistent: 强一致性模式, 每次都要向一个quorum数量的server确定它仍然是leader。

stale: 允许任何server响应读请求。

 

Session

Consul提供了一个session的机制来构建分布式锁。 Session像是一个node, health checks以及key/value数据之间的绑定层, 提供精细的锁。

 

 

在以下情况下, session会失效:

  • 节点注销

  • 任何绑定的health check注销

  • health check未通过

  • session被显示销毁

  • TTL过期

 

当session过期时, session上的锁可能有两种情况: 一是release, 这是默认行为, 二是delete。Session必须在使用前创建, 然后引用它的ID。

Consul中的KV 接口被扩展成支持aquirerelease操作。aquirerelease均通过check-and-set的方式执行。获取锁成功, 则key的LockIndex增加, 当一个锁释放的时候,key对应的ModifyIndex增加。

 

Consul的安全模型

Consul依赖于一个轻量级的gossip以及一个RPC系统提供各种各样的系统(RPC系统在0.8版本中被移除, 官方建议使用HTTP接口)。它们都有各自的安全机制。例如gossip协议使用对称密钥, 共享密钥及密码系统, RPC系统使用端对端加密来完成客户端验证。

这些安全机制都不是默认开启的, 需要自己启用。

推荐的安全机制:

ACL+默认拒绝:Consul配置成启用ACL并且使用白名单方式, 默认拒绝。所有的请求必须有显示的匿名token, 或者验证的ACL token。

开启加密: 开启TCP和UDP加密, 从而使用agent之间的数据连接都是加密的。

 

posted on 2019-12-29 12:21  浮舟z  阅读(777)  评论(0编辑  收藏  举报