最近又需要用fabric来做项目,之前只关注到fabric1.1版本,现在最新的是1.4版本。因此主要看了一些1.4和之前的版本不同的内容。比如1.4增加了etcdraft共识算法。因此接下来会翻译几篇fabric1.4官方文档,供大家参考。基本都是对着google翻译来做的,把一些不符合中文顺序和专业术语的地方,稍微调整下,并且加了一些自己的理解和解释。
下面这篇“配置和管理raft排序服务”,原文链接是:
https://hyperledger-fabric.readthedocs.io/en/latest/raft_configuration.html
如果觉得看得不太理解的时候,可以对着英文版来看。
以下是正文:
配置和管理raft排序服务
适合读者:raft排序节点管理员
概念概述:
对于排序服务的概念和怎样支持排序服务(包括raft),可以查看“排序服务”的文档。
要了解设置排序节点的过程 - 包括创建本地MSP和创建创建块 - 请查看我们关于“设置排序节点”的文档。
一.配置
每个raft节点必须加入系统channel,而不必加入每一个应用channel(解释:因为Raft服务是嵌入在orderer节点里。)并且raft节点可以动态的加入或者退出某个channel,而不影响其他节点。后面的“重设配置”部分描述了该过程。
Raft节点通过tls证书互相认证,如果想冒充一个raft节点,攻击者必须获得tls证书的私钥。总的来说就是,如果没有有效的tls配置,是不可能运行一个raft节点的。
一个raft集群需要配置以下两方面:
- 本地配置。包括治理节点的详细配置,比如tls通信,备份副本的行为和文件存储。
- 管道配置。定义相应的管道下包含的raft集群的成员关系,协议的详细参数,比如心跳频率,领导者超时时间等。
每个channel都有属于它自己的正在运行的raft协议实例。因此,必须在其所属的每个channel的配置中引用该Raft节点,方法是将其服务器和客户端TLS证书(PEM格式)添加到通道配置中。这确保了当其他节点从其接收消息时,它们可以安全地确认发送消息的节点的身份。
(注解: 1个channel可以包含多个raft节点,一个raft节点可以加入多个channel,不同的channel可能包含不同的raft集群,这些不同的raft集群可能会拥有不同的leader节点)
下面的配置来自于configtx.yaml里的片段,展示了在一个channel里包含了三个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将会作为系统channel和任何人们加入的应用channel的共识节点。
(总结:证明channel分两种,一种是系统channel,另一种是用户新建的应用channel)
创建channel配置块后,configtxgen工具将读取TLS证书的路径,并将这些路径替换为证书的相应字节。
第一部分:本地配置
Orderer.yaml配置文件里包含两部分配置是和raft orderer相关的。
一个是集群配置,主要包含tls通信的配置。另一个是共识配置,主要包含写入的日志和快照存储在哪里。
(1)集群参数:
默认情况下, Raft服务在与面向客户端的服务器(用于发送事务或拉块)相同的gRPC服务器上运行,但它可以配置为具有单独的gRPC服务器和单独的端口。
这对于您希望由组织CA颁发的TLS证书,但仅由群集节点用于彼此之间通信的情况以及由面向客户端的API的公共TLS CA颁发的TLS证书的情况非常有用。
- ClientCertificate,ClientPrivateKey:客户端TLS证书和相应私钥的文件路径。
- ListenPort:群集侦听的端口。如果为空,则端口与orderer general port(general.listenPort)的端口相同
- ListenAddress:群集服务正在侦听的地址。
- ServerCertificate,ServerPrivateKey:TLS服务器证书密钥对,在群集服务在单独的gRPC服务器(不同端口)上运行时使用。
- SendBufferSize:规定出口缓冲区中的消息数。
注:ListenPort,ListenAddress,ServerCertificate,ServerPrivateKey必须是一起设置或取消在一起。如果它们未设置,则它们继承自通用TLS部分,例如。general.tls.{privateKey, certificate}
(解释:默认情况下,raft服务的端口和orderer之前互相通信的grpc端口是一样的,但可以把端口配置成不一样。主要用于以下用途,如果不想继承通用TLS的配置,而是使用某些ca组织颁发的TLS证书,配置成不一样后,这些TLS证书则仅限于raft服务集群的节点使用,并且可以和同样使用这些CA组织颁发的证书的客户端进行通信)
其他的一些隐藏的配置参数,比如general.cluster可用于进一步微调集群通信或复制机制:
- DialTimeout,RPCTimeout:指定创建连接和建立流的超时。
- ReplicationBufferSize:为从其他集群节点进行块复制,而分配的内存缓冲区的最大字节数。Raft节点里可以属于多个通道,每个通道都有自己的内存缓冲区,因此可以为不同的channel设置不同的值。默认20971520,即为20MB。
- PullTimeout:排序节点在中止之前等待接收块的最长持续时间。默认为五秒。
- ReplicationRetryTimeout:排序节点在两次连续尝试(重试)之间等待的最长持续时间。默认为五秒。(这是排序节点之前的通信出错后,等待重试的时间)
- ReplicationBackgroundRefreshInterval:连续两次尝试复制添加此节点的现有通道之间的时间,或此节点过去无法复制的通道之间的时间。默认为五分钟。(注解:对于节点正常加入的通道,和过去复制日志失败的通道,定时尝试的时间,默认为5分钟进行一次channel的复制)
(2)共识参数
WALDir:etcd/raft存储Write Ahead Logs的位置。每个通道都有自己的子目录,以通道ID命名。
SnapDir:指定etcd/raft存储快照的位置。每个通道都有自己的子目录,以通道ID命名。
还有一个隐藏的配置参数可以通过在orderer.yaml的共识部分添加以下参数来设置。
- EvictionSuspicion:怀疑已经被channel驱逐(表示channel认为节点已经失去连接)的累积时间段。时间到达后,将会触发节点从其他节点拉取块,并查看它是否已从channel中逐出,以确认其怀疑。如果怀疑被确认(被检查的块不包含该节点的TLS证书),则该节点停止其对该channel的操作。当一个节点不知道任何当选的领导者,也不能被选为该频道的领导者时,该节点怀疑其频道被驱逐。默认为10分钟。
(注解:这个参数主要是用来处理raft集群脑裂或者节点因为某些原因和集群断开连接的处理。)这里应该会有一个类似的机制,如果一直有通信,在区块里能找到节点的tls证书,则不会怀疑,如果长时间没有通信,并且从其他节点拉去块后发现并不包含该节点的tls证书,证明channel已经把该节点剔除在外了。)
这两类参数需要实际调试下,才能知道效果怎样。
第二部分:channel配置
除了已经讨论过的共识参数之外,Raft channel配置还有一个与协议相关的Options配置。目前无法在节点运行时动态更改这些配置的值,必须重设配置并重新启动节点。
唯一的例外是SnapshotIntervalSize参数,可以在运行时调整。
注意:建议避免更改以下值,因为错误的配置可能会导致根本无法选出领导者的状态(例如:如果TickInterval和ElectionTick参数的值都非常低)。在这种配置情况下,领导者节点是无法被选出的,因为领导者需要做出改变。由于存在这样的危险,我们建议大多数情况下不要调整这些参数。
- TickInterval:两次Node.Tick调用之间的时间间隔。
- ElectionTick:Node.Tick选举之间必须通过的调用次数。也就是说,如果追随者在ElectionTick过去之前没有收到当前任期的领导者的任何消息,它将成为候选人并开始选举。
- ElectionTick必须大于HeartbeatTick。
- HeartbeatTick:Node.Tick必须在心跳之间传递的调用数。也就是说,领导者发送心跳消息以维持其领导地位HeartbeatTick。
- MaxInflightBlocks:在乐观复制阶段限制正在进行的附加块的最大数量。
- SnapshotIntervalSize:定义拍摄快照的字节数。
(注意:这里设置的各种tick的次数后,所花的实际时间=TickInterval* Tick的次数。比如,TickInterval=5秒,ElectionTick=3,也就是15秒之内如果收不到leader的任何消息,则节点会成为候选人,发起选举流程。
二.重设配置
Raft orderer支持动态(意味着在通道正在服务时)添加和删除节点,只要一次只添加或删除一个节点。请注意,在尝试重新配置群集之前,群集必须是可操作的并且能够达成共识。例如,如果您有三个节点,并且两个节点发生故障,您将无法通过重新配置群集来删除这些节点。同样,如果在具有三个节点的通道中有一个故障节点,则不应尝试轮换证书,因为这会导致第二个故障。作为一项规则,除非所有共识节点都在线且健康,否则你不应尝试对Raft共识节点进行任何配置更改,例如添加或删除共识节点,或更换共识节点的证书,
如果您决定更改这些参数,建议仅在维护周期中尝试进行此类更改。在仅具有少数节点的群集中,并且其中一个节点已经关闭,这时尝试更新配置,最有可能发生问题。例如,如果您的共识集群中有三个节点,其中一个节点已关闭,则表示三个节点中有两个处于活动状态。如果在此状态下将群集扩展到四个节点,则四个节点中只有两个处于活动状态,这不是法定数量(需要大于一半数量)。那么这时第四个节点将无法登陆,因为节点只能登陆到正常运行的集群(除非集群的总大小为一或两个)。
因此,通过将三个节点的集群扩展到四个节点(而只有两个节点处于活动状态),您实际上讲会被卡住,直到原始离线节点重新正常上线为止。
将新节点添加到Raft群集可以通过以下方式:
- 通过通道配置更新事务将新节点的TLS证书添加到通道。注意:在添加到一个或多个应用程序通道之前,必须将新节点添加到系统通道。
- 从作为系统通道一部分的orderer节点获取系统通道的最新配置块。
- 通过检查所获取的配置块是否包含(即将添加)节点的证书,确保将要添加的节点是系统通道的一部分。
- 使用General.GenesisFile配置参数中配置块的路径 启动新的Raft节点。
- 等待Raft节点从已添加其证书的所有通道的现有节点复制块。完成此步骤后,节点开始为通道提供服务。
- 将新添加的Raft节点的端点添加到所有通道的通道配置中。
在节点本身运行时,可以将已经运行的节点(并且已经参与某些通道)添加到通道。为此,只需将节点的证书添加到通道的通道配置中。节点将自动检测其对新通道的添加(此处的默认值为五分钟,但如果您希望节点更快地检测新通道,请重新启动节点)并从通道中的orderer处提取通道块,然后启动该链的Raft实例。
成功完成后,可以更新通道配置以包括新Raft orderer的endpoint。
从Raft集群中删除节点是通过以下方式完成的:
- 从所有通道的通道配置中删除其endpoint,包括由orderer管理员控制的系统通道。
- 从所有通道的通道配置中删除通过证书认证的节点条目。同样,这包括系统通道。
- 关闭节点。
从特定通道中删除节点,但保持其为其他通道服务是通过以下方式完成的:
- 从通道的通道配置中删除其endpoint。
- 从通道配置中删除通过证书认证的节点条目。
- 第二阶段导致:
- 对于这个删除了该节点的channel,通道中剩余的orderer节点停止与该orderer节点通信。但他们可能仍然在同该节点的其他channel进行通信。
- 从通道中删除的节点将立即或在经过EvictionSuspicion一段时间(默认为10分钟)后自动检测到它已被channel移除,接着将关闭其Raft实例。
三.orderer节点的TLS证书轮换
所有TLS证书的到期日期均由发行方确定。这些到期日期可以从发布之日起10年到最短几个月,因此请咨询您的发行人。在到期日之前,您需要在节点本身和节点所连接的每个通道(包括系统通道)上轮换这些证书。
(解释:order集群里的节点证书是有可能会过期的,因此快过期的时候,为了避免停止所有节点去更换证书,采取逐个节点更新证书,直至所有节点都更新完证书这样的操作,称之为证书轮换)
对于节点参与的每个频道:
- 使用新证书更新通道配置。
- 在节点的文件系统中替换其证书。
- 重新启动节点。
由于节点只能有一个TLS证书密钥对,因此该节点将无法为更新过程中未添加新证书的服务提供服务,从而降低了容错能力。因此, 一旦证书轮换过程开始,就应该尽快完成。
如果由于某种原因TLS证书的轮换已经开始但无法在所有通道中完成,建议将TLS证书转回原来的版本并稍后尝试轮换。
四.度量
有关Operations Service的说明以及如何进行设置,请查看 有关Operations Service的文档。
虽然您优先考虑的指标与您的特定用例和配置有很大关系,但您可能希望监控两个指标:
- consensus_etcdraft_is_leader:标识群集中的哪个节点当前是领导者。如果没有此节点的节点,则代表节点已经和leader节点失联。
- consensus_etcdraft_data_persist_duration:表示对Raft集群的持久写入日志记录执行的写入操作的时间。为了协议安全,消息必须持久保存,fsync在适当的情况下调用,然后才能与同意者集合共享。如果此值开始攀升,则此节点可能无法参与共识(这可能导致此节点和可能的网络的服务中断)。
五.故障排除
- 您对节点施加的压力越大,您可能需要更改某些参数。与任何系统,计算机或机械一样,压力会导致性能下降。正如我们在概念部分中所提到的那样,当跟随者节点一定时间内,没有收到从领导者那里传过来的“心跳”消息或“追加(日志)”消息时,会触发Raft中的领导者选举。因为Raft节点在多个通道中共享相同的通信层(这并不意味着它们共享数据 - 它们不共享!),如果Raft节点是许多通道中的共识集合的一部分,您可能希望延长触发领导者选举的时间,来避免无意(无意义)的领导人的选举。
(解释:多个channel的raft实例可以在同一个orderer节点运行,因此才说raft节点在多个通道中共享相同的通信层。如果触发领导着选举的时间过短,则代表在很短的时间内如果收不到领导节点的消息,则认为已经和领导节点失去联系,而重新进行领导者选举。这样极有可能是其实和领导者并没有失去联系,只是因为网络波动的原因,数据传输出现一定延时而已,频繁的进行领导者重选,会大大降低整个集群的服务性能)