Fabric 1.4源码解读 6:Orderer核心数据结构
前言
许多Orderer的文章,都是从Orderer的启动过程讲起,今天换一种“乐高”角度,先看看有哪些“零件”,再看这些零件怎么配合。
Orderer负责接收交易,把交易打包成区块,然后区块在所有Orderer节点之间达成一致,再分发给Peer的功能,这涉及了:
- 网络:gRPC接收交易,向Peer发送区块
- 切块:把交易打包成区块
- 共识:所有Orderer节点达成一致
这些功能是由Orderer核心数据结构组织起来。
在Fabric中,通道和链在概念上都是一条区块链,所以本文中也会可能会混用链和通道。
核心数据结构
Registrar
代码中,这样描述Registrar:
Registrar serves as a point of access and control for the individual channel resources.
可见它负责了每个channel资源的访问和控制点,也就说,要对某个通道怎么样,得从这入手。
1 | type Registrar struct { |
chains
保存了每一条链,每一条链在Orderer中都以ChainSupport代表。consenters
保存了所有的共识插件,每个共识插件都是一个Consenter,Fabric 1.4中共识插件有Solo、Kafka、EtcdRaft。ledgerFactory
用来读取和创建链的账本。signer
用来对Orderer中的数据进行签名,以及创建SignatureHeader。systemChannelID
和systemChannel
分别是系统链ID、系统链实例。
ChainSupport
ChainSupport汇集了一条通道所需要的所有资源,所以说一个ChainSupport代表了一条链。
1 | type ChainSupport struct { |
ChainSupport 是一堆接口的集合,这些接口构成一条链所有的操作,接口可以分为4类:
- 账本:
ledgerResources
、BlockWriter
分别是账本读写和把区块写入到账本。 - 消息:
msgprocessor.Processor
、cutter
分别是处理交易和把交易切块。 - 共识:
consensus.Chain
是Orderer的共识实例,比如每条链都有自己的Raft共识实例,它们互不干扰。 - 签名:
crypto.LocalSigner
,同Registrar中的介绍。
Chain
Chain是接口,它的实现并不一条链,而是一条链的共识实例,可以是Solo、Kafka和EtcdRaft,它运行在单独的协程,使用Channel和ChainSupport通信,它调用其它接口完成切块,以及让所有的Orderer节点对交易达成一致。
1 | // Chain defines a way to inject messages for ordering. |
Consenter
1 | type Consenter interface { |
Consenter也是接口,它只有1个功能用来创建Chain
。每种共识插件,都有自己单独的consenter实现,分别用来创建solo实例、kafka实例或etcdraft实例。
ConsenterSupport
ConsenterSupport为consenter实现提供所需的资源,其实就是共识用来访问外部数据的接口。
1 | // ConsenterSupport provides the resources available to a Consenter implementation. |
宏观视角
把上面介绍的各项,融合在一幅图中:
- Registrar 包容万象,主要是ChainSupport和Consenter,Consenter是可插拔的
- ChainSupport 代表了一条链,能够指向属于本条链的共识实例,该共识实例由对应共识类型的Consenter创建
- 共识实例使用ConsenterSupport访问共识外部资源