本文已在公众号【Fabric技术分享】发布。
转载请标明出处:
https://blog.csdn.net/qq_27818541/article/details/91479001
本文出自:【BigManing的博客】
1.4.1出现了新的交易排序共识实现(raft),所以花费了几天时间重新阅读了官方原文,探究其最新的思想。并逐字逐句的翻译成中文,方便自己查阅、别人阅读。
这个文章主要讲述了排序服务的定义、各个实现方式以及在交易流程中的作用。根据文中阐述 官方倾向于在生产环境中使用Raft共识进行排序服务,不仅仅是因为它的装箱易用、官方支持,更因为它是官方要实现BFT共识的基础。更多细节都在文中。
受众人群:架构师,排序服务管理员,channel创建者
本主题概述了排序概念,排序节点如何与peer节点互动,他们在交易流程中扮演的角色,以及当前可用的排序服务实施的概述,特别关注raft排序服务实现。
许多分布式区块链,例如以太坊和比特币,未经许可,这意味着任何节点都可以参与共识过程,其中交易被排序并捆绑成块。由于这一事实,这些系统依赖于概率共识算法,这种算法最终保证了分类账一致性的高度概率,但仍然容易受到不同分类账(也称为分类账“分叉”)的影响,网络中的不同参与者对已接受的交易顺序的不同看法。
Hyperledger Fabric的工作方式不同。它具有一种称为orderer的节点 (它也称为“排序节点”),它执行此事务排序,与其他节点一起形成排序服务。由于Fabric的设计依赖于确定性一致性算法,因此排序服务生成的任何peer验证都将保证最终和正确。分类帐不能像许多其他分布式区块链那样分叉。
除了促进一致性之外,将链码执行(在peer节点上发生)的认可与排序分开,使Fabric在性能和可伸缩性方面具有优势,消除了在由相同节点执行和排序时可能发生的瓶颈。
除了排序角色之外,oderer还维护允许创建channel的组织列表。这个组织列表被称为“联合体”,列表本身保存在“oderer系统通道”(也称为“订购系统通道”)的配置中。默认情况下,此列表及其所在的channel只能由oderer管理员编辑。请注意,排序服务可能会持有其中几个列表,这使得该联盟成为Fabric多租户的工具。
oderer还对channel实施基本访问控制,限制谁可以向他们读取和写入数据,以及谁可以配置它们。请记住,有权修改channel中配置元素的人员必须遵守相关管理员在创建联盟或channel时设置的策略。配置事务由排序节点处理,因为它需要知道当前的一组策略以执行其基本形式的访问控制。在这种情况下,oderer处理配置更新以确保请求者具有适当的管理权限。如果是,则orderer根据现有配置验证更新请求,生成新的配置事务,并将其打包到一个块中,该块将中继到通道上的所有peer。
与区块链网络交互的所有对象(包括peer,应用程序,管理员和oderer)都会从其数字证书及其成员服务提供商(MSP)定义中获取其组织身份。
有关身份和MSP的更多信息,请查看我们关于身份和成员身份的文档 。
就像peer节点一样,订购节点属于一个组织。与peer节点类似,每个组织都应使用单独的证书颁发机构(CA)。此CA是作为根CA运行,还是选择部署根CA,然后再部署与该根CA关联的中间CA,由您决定。
我们从Peers的文章中看到,它们构成了区块链网络的基础,托管分类账,可以通过智能合约由应用程序查询和更新。
具体而言,想要更新分类帐的应用程序涉及具有三个阶段的流程,以确保区块链网络中的所有peer保持其分类帐彼此一致。
在第一阶段,客户端应用程序将一个事务提案发送给peer子集,这些peer将调用智能合约以生成提议的分类帐更新,然后对结果进行认可。支持peer此时不会将建议的更新应用于其分类帐副本。相反,背书节点将提议响应返回给客户端应用程序。经批准的交易提案最终将在第二阶段被排序为块,然后分发给所有peer以进行最终验证并在第三阶段提交。
要深入了解第一阶段,请参阅Peers主题。
在事务的第一阶段完成之后,客户端应用程序已经从一组peer接收到认可的事务提案响应。现在是交易第二阶段的时候了。
在此阶段,应用程序客户端将包含已签署的事务提案响应的事务提交给排序服务节点。排序服务创建交易块,最终将其分发给通道上的所有peer以进行最终验证并在第三阶段提交。
排序服务节点同时从许多不同的应用程序客户端接收事务。这些排序服务节点一起工作以共同形成排序服务。它的工作是将批量提交的事务安排到明确定义的序列中,并将它们打包成块。这些块将成为区块链的块!
块中的事务数取决于与所需大小相关的通道配置参数和块的最大超时时间(BatchSize以及BatchTimeout准确的参数)。然后将这些块保存到排序节点的分类帐,并分发给已加入该channel的所有peer节点。如果此时peer恰好关闭,或稍后加入通道,它将在重新连接到排序服务节点之后接收块,或者通过与另一个peer闲聊。我们将在第三阶段看到对象如何处理此块。
排序节点的第一个角色是打包分类帐更新。在该示例中,应用程序A1将由E1和E2认可的事务T1发送到odererO1。并行地,应用程序A2将由E1认可的事务T2发送给排序节点O1。O1将来自应用程序A1的事务T1和来自应用程序A2的事务T2与来自网络中的其他应用程序的其他事务一起打包到块B2中。我们可以看到在B2中,交易订单是T1,T2,T3,T4,T6,T5 - 这可能不是这些交易到达排序节点的顺序!(此示例显示了一个非常简化的排序服务配置,只有一个订购节点。)
值得注意的是,块中的事务排序不一定与排序服务接收的顺序相同,因为可能存在多个同时接收事务的排序服务节点。重要的是排序服务将交易置于严格的排序中,并且在验证和提交交易时,peer节点将使用此订单。
块内事务的这种严格排序使Hyperledger Fabric与其他区块链略有不同,其他区块链可以将相同的事务打包成多个不同的块,这些块竞争形成链。在Hyperledger Fabric中,排序服务生成的块是 最终的。一旦交易被写入一个区块,它在分类账中的位置就会得到确定。正如我们之前所说,Hyperledger Fabric的最终结果意味着没有分类账分叉 - 经验证的交易永远不会被还原或丢弃。
我们也可以看到,虽然peer节点执行智能合约和处理交易,但是oderder绝对不会。到达排序节点的每个授权交易都是机械打包在一个区块中 - 排序节点不会对交易内容做出判断(通道配置交易除外,如前所述)。
在第二阶段结束时,我们看到排序节点负责收集建议的交易更新,排序它们,并将它们打包成块,准备分发的简单但至关重要的过程。
事务工作流的第三阶段涉及从排序节点到peer的块的分发和后续验证,其中它们可以应用于分类帐。
阶段3开始于排序节点将块分配给连接到它的所有peer。值得注意的是,并非每个peer都需要连接到一个oderer - peer可以使用gossip协议将块级联到其他peer。
每个peer将独立地验证分布式块,但是以确定的方式确保分类块保持一致。具体来说,通道中的每个peer都将验证块中的每个事务,以确保它已得到所需组织的peer的认可,其背书认可匹配,最初认可的交易可能已经在进行中的其他近期承诺的交易没有使其无效。未经验证的事务仍保留在由排序节点创建的不可变块中,但它们被peer标记为无效,并且不更新分类帐的状态。
排序节点的第二个作用是将块分发给peer。在该示例中,odererO1将块B2分配给peerP1和peerP2。P1处理块B2,导致在P1上将新块添加到分类账L1上。并行地,peerP2处理块B2,导致在P2将新块添加到分类账L1上。一旦完成该过程,就在peerP1和P2上一致地更新分类账L1,并且每个分类账可以通知连接的应用程序已经处理了该事务。
总之,第三阶段将排序服务生成的块一致地应用于分类帐。将事务严格排序到块中允许每个peer验证在区块链网络上一致地应用事务更新。
有关阶段3的更深入了解,请参阅Peers主题。
虽然当前可用的每个排序服务以相同的方式处理事务和配置更新,但是仍然有几种不同的实现方式用于在排序服务节点之间对事务的严格排序达成共识。
有关如何建立订购节点(无论将使用该节点的实现如何),请查看our documentation on standing up an ordering node。
排序服务的Solo实现恰当地其命名:它只有一个排序节点。因此,它不是,也永远不会是容错的。出于这个原因,Solo实现不能用于生产环境,但它们是测试应用程序和智能合约或创建概念证明的不错选择。但是,如果您希望将此PoC网络扩展到生产环境中,您可能希望从单个节点Raft集群开始,因为它可能会重新配置以添加其他节点。
1.4.1开始新增的,Raft是一种基于etcd中Raft协议实现的崩溃容错(CFT)订购服务。Raft遵循“领导者和追随者”模型,其中选举领导者节点(每个channel)并且其决定由追随者复制。与基于Kafka的排序服务相比,Raft排序服务应该更容易设置和管理,并且它们的设计允许不同的组织为分布式排序服务贡献节点。
与基于Raft的排序类似,Apache Kafka是一种使用“领导者和关注者”节点配置的CFT实现。Kafka利用ZooKeeper集合进行管理。自Fabric v1.0以来,基于Kafka的排序服务已经可用,但许多用户可能会发现管理Kafka集群的额外管理开销令人生畏或不受欢迎。
如上所述,在开发测试,开发或概念验证网络时,Solo排序服务是一个不错的选择。出于这个原因,它是我们构建您的第一个网络教程中部署的默认排序服务,因为从其他网络组件的角度来看,Solo排序服务处理事务与更复杂的Kafka和Raft实现相同,同时节省了管理维护和升级多个节点和集群的开销。由于Solo排序服务不具备容错能力,因此绝不应将其视为生产区块链网络的可行替代方案。对于希望仅以单个排序节点开始但可能希望在未来增长的网络,单个节点Raft集群是更好的选择。
有关如何配置Raft排序服务,请查看documentation on configuring a Raft ordering service]。
生产网络的首选排序服务选择,Fabric实现了建立以Raft协议“领导者和追随者”模型,其中领导者在channel中的订购节点之间动态选出(这个节点集合称为“consenter set”),该领导者将消息复制到跟随者节点。由于系统可以承受节点(包括领导节点)的丢失,只要剩下大多数排序节点(即所谓的“法定人数”),Raft就被称为“崩溃容错”(CFT)。换句话说,如果一个通道中有三个节点,它可以承受一个节点的丢失(剩下两个节点)。如果通道中有五个节点,则可能会丢失两个节点(剩余三个节点)。
从他们提供给网络或channel的服务的角度来看,Raft和现有的基于Kafka的排序服务(我们将在后面讨论)是类似的。他们都是使用领导者和追随者设计的CFT排序服务。如果您是应用程序开发人员,智能合约开发人员或peer节点管理员,您将不会注意到基于Raft与Kafka的排序服务之间的功能差异。但是,有一些主要的差异值得考虑,特别是如果您打算管理排序服务:
注意:Solo与Kafka类似,Raft排序服务可能会在确认收据已发送给客户后丢失交易。例如,如果领导者在跟随者提供接收确认的大致相同时间崩溃。因此,应用程序客户端应该在peer上监听事务提交事件(以检查事务有效性),但应格外小心, 确保客户端也能正常优雅的处理在配置的时间范围内未提交事务的超时。根据应用程序,可能需要重新提交事务或在此类超时时收集一组新的背书认可。
虽然Raft提供了许多与Kafka相同的功能 - 虽然它采用更简单易用的包装 - 但其功能与Kafka的功能大不相同,并向Fabric引入了许多新概念或现有概念的新解释。
Log entry(日志条目)
Raft排序服务中的主要工作单元是“日志条目”,这些条目的完整序列称为“日志”。如果成员的多数(法定人数,换言之)成员就条目及其顺序达成一致,我们认为日志是一致的,从而在各个oderer上进行日志复制。
Consenter set(共识集合)
排序节点主动参与给定channel的共识机制并接收channel的复制日志。这可以是所有可用节点(在单个群集中或在对系统通道有贡献的多个群集中),或者是这些节点的子集。
Finite-State Machine (FSM)(状态机)
Raft中的每个排序节点都有一个FSM,它们共同用于确保各个排序节点中的日志序列是确定性的(以相同的顺序编写)。
Quorum(法定人数)
描述需要确认提案的最少数量的同意者,以便可以订购交易。对于每个consenter集合,采用大多数节点的原则。在具有五个节点的群集中,必须有三个节点才能达到法定人数。如果由于任何原因导致法定数量的节点不可用,则排序服务集群将无法用于通道上的读取和写入操作,并且不能提交新日志。
Leader(领导者)
这不是一个新概念 - 正如我们所说,Kafka也使用领导者 。在任何特定时间,channel的共识集合选择一个节点作为领导者是至关重要的 。领导者负责提取新的日志条目,将它们复制到跟随者订购节点,以及管理何时认为条目已提交。这不是特殊类型的排序节点。根据情况确定,这只是排序节点在某些时候可能拥有的角色,而不是其他角色。
Follower(追随者)
同样,这不是一个新概念,但了解Follower的关键是跟随者从领导者那里接收日志并确定性地复制它们,确保日志保持一致。正如我们在关于领导者选举的章节中所看到的,追随者也会收到来自领导者的“心跳”信息。如果领导者停止在可配置的时间内发送这些消息,则关注者将发起领导者选举,其中一人将被选为新领导者 。
每个channel都在单独的Raft协议实例上运行,这允许每个实例选择不同的领导者。此配置还允许在集群由不同组织控制的排序节点组成的用例中进一步分散服务。虽然所有Raft节点必须是系统通道的一部分,但它们不一定必须是所有应用程序通道的一部分。channel创建者(和channel管理员)可以选择可用排序节点的子集,并根据需要添加或删除订购节点(只要一次只添加或删除一个节点)。
虽然这种配置以冗余心跳消息和goroutine的形式产生了更多的开销,但它为BFT奠定了必要的基础。
在Raft中,交易(以提议或配置更新的形式)由接收交易的订购节点自动路由到该channel的当前领导者。这意味着peer和应用程序在任何特定时间不需要知道领导节点是谁。只有订购节点需要知道。
当排序节点验证检查完成后,交易将被订购,打包成块,同意和分配,如我们的交易流程的第二阶段所述。
虽然选举领导者的过程发生在排序节点的内部流程中,但值得注意的是流程是如何运作的。
raft节点始终处于以下三种状态之一:跟随者,候选者或领导者。所有节点最初都是作为跟随者开始的。在这种状态下,他们可以接受来自领导者的日志条目(如果有已经当选的节点),或者为领导者投票。如果在设定的时间内没有收到日志条目或心跳(例如,五秒),则节点会自我提升到候选状态。在候选状态中,节点请求来自其他节点的投票。如果候选人获得法定数量的选票,则将其提升为领导者。领导者必须接受新的日志条目并将其复制给跟随者。
有关领导者选举过程如何运作的直观表示,请查看The Secret Lives of Data。
如果订购节点出现故障,它如何在重新启动时获取错过的日志?
虽然可以无限期地保留所有日志,但为了节省磁盘空间,Raft使用一个名为“snapshotting”的进程,用户可以在其中定义将在日志中保留多少字节的数据。此数据量将符合一定数量的块(这取决于块中的数据量。请注意,只有完整块存储在快照中)。
例如,假设滞后副本R1刚刚重新连接到网络。它的最新版块是100。领导者L处于阻止状态196,并配置为对数据量进行快照,在这种情况下,数据量代表20个块。R1因此将从L接收块180 然后再调用Deliver请求用于接收块101到块180。块180到196将被复制到R1 通过正常raft协议。
Fabric支持的另一种崩溃容错排序服务是Kafka分布式流平台的改编版,用作订购节点集群。您可以在Apache Kafka网站上阅读有关Kafka的更多信息,但在较深的层面上,Kafka使用Raft使用的相同概念“领导者和跟随者”配置,其中交易(Kafka称之为“消息”)从领导者复制节点到跟随节点。如果领导者节点发生故障,其中一个跟随者成为领导者,并且可以继续订购,确保容错,就像使用Raft一样。
Kafka集群的管理,包括任务协调,集群成员资格,访问控制和管理员选举等,由ZooKeeper集合及其相关API处理。
Kafka集群和ZooKeeper集合的设置非常棘手,因此我们的文档假定了Kafka和ZooKeeper的工作知识。如果您决定在没有这方面专业知识的情况下使用Kafka,您应该在尝试使用基于Kafka的排序服务之前至少完成Kafka快速入门指南的前六个步骤。您还可以查阅 此示例配置文件 ,以获取Kafka和ZooKeeper的合理默认值的简要说明。
要了解如何启动基于Kafka的排序服务,请查看我们关于Kafka的文档。