1. RAFT排序服务介绍
在fabric1.4.1的版本中,提供了基于raft共识的raft排序服务。raft的模型可以容忍崩溃,如果有节点故障掉线可以正常运行。前提是要有大多数存活,也就是要保证1/2以上的节点个数正常运行。raft共识是“主从模型”,主节点通过动态选举决定,从节点是主节点的复制。raft排序服务比kafka排序服务易于设置和管理。并且raft的设计允许不同的组织贡献节点来共同组成排序服务。
2. RAFT排序和kafka排序的对比
从提供服务的视角来看,基于raft和kafka的排序服务是类似的,他们都是基于CFT(crash fault tolerant)模型的排序服务,并且都使用了主从节点的设置。如果你是应用开发者或者智能合约开发者,你不会注意到他们之间的却别。但是,有一些主要的区别值得探讨,尤其是你需要管理排序服务。
- kafka和zookeeper的设计不适用于大型网络。它们的设计是CFT模型,但局限于运行的比较紧密的主机上。也就是说,需要有一个组织专门运行kafka集群。鉴于此,当有多个组织使用基于kafka排序服务的时候,其实没有实现区中心化,因为所有的节点连接的都是由一个组织单独控制的kafka集群。如果使用raft,每个组织可以贡献排序节点,共同组成排序服务,可以更好的区中心化。
- raft是原生支持的,而kafka需要经过复杂的步骤部署,并且需要单独学习成本。而且kafka和zookeeper的支持相关的issue要通过apache来处理,而不是hyperledger fabric。raft的实现是包含在fabric社区的,开发支持更加便利。
-
系统架构不同
3.1 kafka共识
在kafka共识模式中,orderer与orderer之间不会互相直接建立连接,而是与kafka连接。这种共识模式中,依赖于外部的kafka集群系统和zookeeper集群系统。每个orderer会把自己的交易发送给kafka集群,交易在kafka对应的topic中排序后,kafka把排序后的交易推送给orderer节点。Orderer节点收到交易后对交易打包,然后发给peer。kafka.jpg
3.2 etcdraft共识
在etcdraft共识模式中,orderer与orderer之间直接建立连接,不依赖外部系统。在orderer节点中,会创建raft的协程来处理与其他orderer的通信。etcd.jpg
3. RAFT排序服务的目的
raft排序是fabric实现拜占庭容错排序服务的第一步,如我们所见,开发raft排序服务的决定也是基于此的。
4. 配置RAFT共识
raft节点之间通过使用TLS认证身份,如果一个攻击者想要伪造raft节点,就必须要获得一个有效的证书和对应的私钥。所以,没有一个有效的TLS证书,是不可能运行raft节点的。
要使用raft共识,需要修改两个地方
- 本地配置:用来控制节点的特性,例如TLS配置,备份个数和文件存储。
- 通道配置:用来定义raft集群的成员关系,以及raft协议相关的参数,例如心跳间隔、leader节点超时时间等。
需要注意的是,每个channel有属于它自己的raft集群。因此,在chennel中要指定raft节点,指定的方式是把raft节点的tls证书配置到channel的配置文件中。在系统通道和应用通道中的配置中,每个排序以consenter的形式列出来。下面是configtx.yaml中关于raft节点配置的章节。
Consenters:
- Host: raft0.example.com
Port: 7050
ClientTLSCert: path/to/ClientTLSCert0
ServerTLSCert: path/to/ServerTLSCert0
- Host: raft1.example.com
Port: 7050
ClientTLSCert: path/to/ClientTLSCert1
ServerTLSCert: path/to/ServerTLSCert1
- Host: raft2.example.com
Port: 7050
ClientTLSCert: path/to/ClientTLSCert2
ServerTLSCert: path/to/ServerTLSCert2
本地配置
orderer.yaml配置文件中有两个关于raft排序配置的章节,分别问cluster和Consensus
- cluster,主要用来决定tls通信配置
- ClientCertificate, ClientPrivateKey : 客户端证书和私钥(general.tls.{privateKey, certificate})。
- ListenPort:对外提供服务的端口 (general.listenPort)。
- ListenAddress : 本地监听的地址。
- ServerCertificate, ServerPrivateKey : 服务端的证书和私钥。
- SendBufferSize : 发送区缓存大小。
注意:ListenPort, ListenAddress, ServerCertificate, ServerPrivateKey这几个配置项,只能同时设置或者同时不设置。
- cluster
- WALDir : raft的WAL(Write Ahead Logs)存放位置,每个通道需要有以它自己的channel ID为前缀命名的子目录。
- SnapDir : raft的快照存放位置,每个通道需要有以它自己的channel ID为前缀命名的子目录。
通道配置
当节点启动后,如果想要更改配通道置并且使配置生效,只有重启节点服务。有一个例外是SnapshotIntervalSize配置项,它可以在运行时动态调整。
- TickInterval : 两次Node.Tick调用的时间间隔。
- ElectionTick : 如果follower在当前阶段,经过ElectionTick次的时间后,没有从主节点收到任何消息,follower将会成为候选节点并发起选举。
- HeartbeatTick : 主节点在HeartbeatTick间隔内回发送心跳信息给从节点,来保持它主节点的身份。
- ElectionTick必须大于HeartbeatTick
- MaxInflightBlocks : 在乐观复制阶段限制正在进行的附加块的最大数量。
- SnapshotIntervalSize:每个快照的大小。