Fabric设计 - 基于kafka的排序服务
须知(Caveat emptor)
This document assumes that the reader generally knows how to set up a Kafka
cluster and a ZooKeeper ensemble. The purpose of this guide is to identify the
steps you need to take so as to have a set of Hyperledger Fabric ordering
service nodes (OSNs) use your Kafka cluster and provide an ordering service to
your blockchain network.
该文档假设读者已经基本了解如何去搭建Kafka集群和ZooKeeper集群。本文档的目的是确定您使用Kafka集群搭建一套Hyperledger Fabric排序服务节点集(OSNs)以及为你的区块链网络提供排序服务所需要采取的步骤。
概览(Big picture)
Each channel maps to a separate single-partition topic in Kafka.
每一个通道(channel)在Kafka中被映射到一个单独的单分区(partition)类别(topic)。(译者注:通常每个Topic包含一个或多个Partition,此处每个Topic只包含一个Partition)
When an OSN receives transactions via the Broadcast
RPC, it checks to make sure
that the broadcasting client has permissions to write on the channel, then
relays (i.e. produces) those transactions to the appropriate partition in Kafka.
当排序节点通过RPC广播
(Broadcast
)接收到交易时,它会检查广播交易的客户端是否有权限去修改通道(channel)数据,然后反馈(即产生)这些交易到Kafka的适当分区(partition)中。
This partition is also consumed by the OSN which groups the received
transactions into blocks locally, persists them in its local ledger, and serves
them to receiving clients via the Deliver
RPC.
该分区也被排序节点所消费(consume),排序节点将接收到的交易分组写入到本地区块,将其保留在本地账本中,并通过Deliver
RPC提供给需要接收的客户端。
For low-level details, refer
to the document that describes how we came to this design <https://docs.google.com/document/d/1vNMaM7XhOlu9tB_10dKnlrhy5d7b1u8lSY8a-kVjCO4/edit>
_
— Figure 8 is a schematic representation of the process described above.
更多详细的信息,请参考the document that describes how we came to this design <https://docs.google.com/document/d/1vNMaM7XhOlu9tB_10dKnlrhy5d7b1u8lSY8a-kVjCO4/edit>
_
— 图8是上述过程的示意图。
步骤(Steps)
Let K
and Z
be the number of nodes in the Kafka cluster and the
ZooKeeper ensemble respectively:
设定变量 K
和 Z
分别是Kafka集群和ZooKeeper集群的节点数量:
i. At a minimum, K
should be set to 4. (As we will explain in Step 4 below,
this is the minimum number of nodes necessary in order to exhibit crash fault
tolerance, i.e. with 4 brokers, you can have 1 broker go down, all channels will
continue to be writeable and readable, and new channels can be created.)
i. K
的最小值需要是4。(我们将在步骤4中解释,这是实现 故障容错(crash fault tolerance) 所需要的最小数值,也就是说,
4个节点可以容许1个节点宕机,所有的通道能够继续读写且可以创建通道。)(译者:Kafka节点被称为broker)
ii. Z
will either be 3, 5, or 7. It has to be an odd number to avoid
split-brain scenarios, and larger than 1 in order to avoid single point of
failures. Anything beyond 7 ZooKeeper servers is considered an overkill.
ii. Z
可以是3、5或者7。它必须是一个奇数来避免分裂(split-brain)情景,大于1以避免单点故障。
超过7个ZooKeeper服务器则被认为是多余的。
Proceed as follows:
请按照以下步骤进行:
Orderers: Encode the Kafka-related information in the network’s genesis
block. If you are usingconfigtxgen
, editconfigtx.yaml
— or pick a
preset profile for the system channel’s genesis block — so that:Orderers: Kafka 相关信息被写在网络的初始区块中. 如果你使用
configtxgen
工具, 编辑configtx.yaml
文件— 或者挑一个现成的系统通道的初始区块配置文件 — 其中:a. ``Orderer.OrdererType`` is set to ``kafka``.
a. ``Orderer.OrdererType`` 字段被设置为 ``kafka``.
b. ``Orderer.Kafka.Brokers`` contains the address of *at least two* of the
Kafka brokers in your cluster in ``IP:port`` notation. The list does not
need to be exhaustive. (These are your seed brokers.)
b. ``Orderer.Kafka.Brokers`` 字段包含 *至少两个* Kafka集群中的节点``IP:port`` 样式的地址。这个列表没有必要详尽无遗(这些是你的 seed brokers.)
Orderers: Set the maximum block size. Each block will have at most
Orderer.AbsoluteMaxBytes
bytes (not including headers), a value that you can
set inconfigtx.yaml
. Let the value you pick here beA
and make note of
it — it will affect how you configure your Kafka brokers in Step 4.Orderers: 设置区块最大容量. 每一个区块最多只能有
Orderer.AbsoluteMaxBytes
bytes的容量(不含区块头信息), 这是一个你可以修改的值,存放在configtx.yaml
配置文件中. 假设此处你设置的数值为A
,将此数字记下来 — 这会影响你在步骤4中对于Kafka brokers 的配置.Orderers: Create the genesis block. Use
configtxgen
. The settings you
picked in Steps 1 and 2 above are system-wide settings, i.e. they apply across
the network for all the OSNs. Make note of the genesis block’s location.Orderers: 使用
configtxgen
工具 创建初始区块. 在步骤1和2中的设置是全局的设置, 也就是说这些设置的生效范围是网络中所有的排序节点. 记录下初始区块的位置.Kafka cluster: Configure your Kafka brokers appropriately. Ensure that
every Kafka broker has these keys configured:Kafka 集群: 适当配置你的Kafka集群. 确保每一个Kafka节点都配置了以下的值:
a.
unclean.leader.election.enable = false
— Data consistency is key in
a blockchain environment. We cannot have a channel leader chosen outside of
the in-sync replica set, or we run the risk of overwriting the offsets that
the previous leader produced, and —as a result— rewrite the blockchain
that the orderers produce.a.
unclean.leader.election.enable = false
— 数据一致性是区块链环境的关键. 我们不能选择不在同步副本集中的channel leader, 也不能冒风险去覆盖前一leader所产生的偏移量, 那样的结果就是重写orderers所产生的区块链数据.b.
min.insync.replicas = M
— Where you pick a valueM
such that
1 < M < N (seedefault.replication.factor
below). Data is considered
committed when it is written to at leastM
replicas (which are then
considered in-sync and belong to the in-sync replica set, or ISR). In any
other case, the write operation returns an error. Then:b.
min.insync.replicas = M
—M
的值需要满足
1 < M < N (N的值参考后面的default.replication.factor
). 数据被认为是完成提交当它被写入到至少M
个副本中(也就是说它被认为是同步的,然后被写入到同步副本集中,也成为ISR). 其他情况, 写入操作返回错误信息. 然后:i. If up to N-M replicas -- out of the N that the channel data is
written to -- become unavailable, operations proceed normally.
i. 如果有 N-M 个副本不可访问, 操作将正常进行.
ii. If more replicas become unavailable, Kafka cannot maintain an ISR
set of M, so it stops accepting writes. Reads work without issues.
The channel becomes writeable again when M replicas get in-sync.
ii. 如果更多副本不可访问, Kafka 不能位置数量 M 的同步副本集(ISR), 所以它会停止接受写入操作. 读操作可以正常运行.
当M个副本重新同步后,通道就可以再次变为可写入状态.
c. ``default.replication.factor = N`` -- Where you pick a value ``N`` such
that N < K. A replication factor of ``N`` means that each channel will have
its data replicated to ``N`` brokers. These are the candidates for the ISR
set of a channel. As we noted in the ``min.insync.replicas section`` above,
not all of these brokers have to be available all the time. ``N`` should be
set *strictly smaller* to ``K`` because channel creations cannot go forward
if less than ``N`` brokers are up. So if you set N = K, a single broker
going down means that no new channels can be created on the blockchain
network -- the crash fault tolerance of the ordering service is
non-existent.
c. ``default.replication.factor = N`` -- 选择一个 ``N`` 的数值满足 N < K (Kafak集群数量). 参数 ``N`` 表示每个channel 的数据会复制到 ``N`` 个 broker 中. 这些是 channel 同步副本集的候选. 正如前面 ``min.insync.replicas`` 部分所说的, 不是所有broker都需要是随时可用的. ``N`` 值需要设置为绝对小于 ``K`` , 因为channel的创建需要不少于 ``N`` 个broker是启动的. 所以如果设置 N = K , 一个 broker 宕机就意味着区块链网络不能再创建channel. 那幺故障容错的排序服务也就不存在了.
d. ``message.max.bytes`` and ``replica.fetch.max.bytes`` should be set to a
value larger than ``A``, the value you picked in
``Orderer.AbsoluteMaxBytes`` in Step 2 above. Add some buffer to account for
headers -- 1 MiB is more than enough. The following condition applies:
d. ``message.max.bytes`` 和 ``replica.fetch.max.bytes`` 的值需要大于 ``A``, 就是在步骤2中选取的 ``Orderer.AbsoluteMaxBytes`` 的值. 再为区块头增加一些余量 -- 1 MiB 就足够了. 需要满足以下条件:
::
Orderer.AbsoluteMaxBytes < replica.fetch.max.bytes <= message.max.bytes
(For completeness, we note that ``message.max.bytes`` should be strictly
smaller to ``socket.request.max.bytes`` which is set by default to 100 MiB.
If you wish to have blocks larger than 100 MiB you will need to edit the
hard-coded value in ``brokerConfig.Producer.MaxMessageBytes`` in
``fabric/orderer/kafka/config.go`` and rebuild the binary from source.
This is not advisable.)
(补充, 我们注意到 ``message.max.bytes`` 需要严格小于 ``socket.request.max.bytes`` , 这个值默认是100Mib. 如果你希望区块大于100MiB, 你需要去修改硬代码中的变量 ``brokerConfig.Producer.MaxMessageBytes`` , 代码位置是 ``fabric/orderer/kafka/config.go`` , 再重新编译代码, 不建议这幺做.)
e. ``log.retention.ms = -1``. Until the ordering service adds
support for pruning of the Kafka logs, you should disable time-based
retention and prevent segments from expiring. (Size-based retention -- see
``log.retention.bytes`` -- is disabled by default in Kafka at the time of
this writing, so there's no need to set it explicitly.)
e. ``log.retention.ms = -1``. 直到排序服务增加了对于 Kafka 日志分割(pruning)的支持之前, 应该禁用基于时间分割的方式以避免单个日志文件到期分段. (基于文件大小的分割方式 -- 看参数 ``log.retention.bytes`` -- 在本文书写时, 在 Kafka 中是默认被禁用的, 所以这个值没有必要指定地很明确. )
Based on what we've described above, the minimum allowed values for ``M``
and ``N`` are 2 and 3 respectively. This configuration allows for the
creation of new channels to go forward, and for all channels to continue to
be writeable.
基于上文所描述的, ``M`` 和 ``N`` 的最小值分别为 2 和 3 . 这个配置可以创建 channel 并让所有 channel 都是随时可以写入的.
Orderers: Point each OSN to the genesis block. Edit
General.GenesisFile
inorderer.yaml
so that it points to the genesis
block created in Step 3 above. (While at it, ensure all other keys in that YAML
file are set appropriately.)Orderers: 将所有排序节点指向初始区块. 编辑
orderer.yaml
文件中的参数General.GenesisFile
使其指向步骤3中所创建的初始区块. (同时, 确保YAML文件中所有其他参数都是正确的.)Orderers: Adjust polling intervals and timeouts. (Optional step.)
Orderers: 调整轮询间隔和超时时间. (可选步骤.)a. The
Kafka.Retry
section in theorderer.yaml
file allows you to
adjust the frequency of the metadata/producer/consumer requests, as well as
the socket timeouts. (These are all settings you would expect to see in a
Kafka producer or consumer.)a.
orderer.yaml
文件中的Kafka.Retry
区域让你能够调整 metadata/producer/consumer 请求的频率以及socket的超时时间. (这些应该就是所有在 kafka 的生产者和消费者 中你需要的设置)b. Additionally, when a new channel is created, or when an existing channel
is reloaded (in case of a just-restarted orderer), the orderer interacts
with the Kafka cluster in the following ways:b. 另外, 当一个 channel 被创建, 或当一个现有的 channel 被重新读取(刚启动 orderer 的情况), orderer 通过以下方式和 Kafka 集群进行交互.
a. It creates a Kafka producer (writer) for the Kafka partition that
corresponds to the channel.
a. 为 channel 对应的 Kafka 分区 创建一个 Kafka 生产者.
b. It uses that producer to post a no-op ``CONNECT`` message to that
partition.
b. 通过生产者向这个分区发一个空的连接信息.
c. It creates a Kafka consumer (reader) for that partition.
c. 为这个分区创建一个 Kafka 消费者.
If any of these steps fail, you can adjust the frequency with which they
are repeated. Specifically they will be re-attempted every
``Kafka.Retry.ShortInterval`` for a total of ``Kafka.Retry.ShortTotal``,
and then every ``Kafka.Retry.LongInterval`` for a total of
``Kafka.Retry.LongTotal`` until they succeed. Note that the orderer will
be unable to write to or read from a channel until all of the steps
above have been completed successfully.
如果任意步骤出错, 你可以调整其重复的频率.
这些步骤会在每一个 Kafka.Retry.ShortInterval 指定的时间间隔后进行重试 Kafka.Retry.ShortTotal 次,
再以 Kafka.Retry.LongInterval 规定的时间间隔重试 Kafka.Retry.LongTotal 次直到成功.
需要注意的是 orderer 不能读写该 channel 的数据直到所有上述步骤都成功执行.
Set up the OSNs and Kafka cluster so that they communicate over SSL.
(Optional step, but highly recommended.) Refer tothe Confluent guide <http://docs.confluent.io/2.0.0/kafka/ssl.html>
_ for the Kafka cluster side of
the equation, and set the keys underKafka.TLS
inorderer.yaml
on every
OSN accordingly.将排序节点和 Kafka 集群间设置为通过 SSL 通讯.
(可选步骤,强烈推荐) 参考the Confluent guide <http://docs.confluent.io/2.0.0/kafka/ssl.html>
_ 文档中关于 Kafka 集群的设置, 来设置每个排序节点orderer.yaml
文件中Kafka.TLS
部分的内容.Bring up the nodes in the following order: ZooKeeper ensemble, Kafka
cluster, ordering service nodes.启动节点请按照以下顺序: ZooKeeper 集群, Kafka 集群, 排序节点
其他注意事项(Additional considerations)
Preferred message size. In Step 2 above (see
Steps
_ section) you can
also set the preferred size of blocks by setting theOrderer.Batchsize.PreferredMaxBytes
key. Kafka offers higher throughput when
dealing with relatively small messages; aim for a value no bigger than 1 MiB.首选的消息大小. 在上面的步骤2中, 你也能通过参数
Orderer.Batchsize.PreferredMaxBytes
设置首选的区块大小.
Kafka 处理相对较小的信息有更高的吞吐量; 针对小于 1 MiB 大小的值.Using environment variables to override settings. You can override a
Kafka broker or a ZooKeeper server’s settings by using environment variables.
Replace the dots of the configuration key with underscores —
e.g.KAFKA_UNCLEAN_LEADER_ELECTION_ENABLE=false
will allow you to override
the default value ofunclean.leader.election.enable
. The same applies to the
OSNs for their local configuration, i.e. what can be set inorderer.yaml
.
For exampleORDERER_KAFKA_RETRY_SHORTINTERVAL=1s
allows you to override the
default value forOrderer.Kafka.Retry.ShortInterval
.使用环境变量重写设置. 你能够通过设置环境变量来重写 Kafka 节点和 Zookeeper 服务器的设置. 替换配置参数中的 点 为 下划线 — 例如
KAFKA_UNCLEAN_LEADER_ELECTION_ENABLE=false
环境变量重写配置参数unclean.leader.election.enable
. 环境变量重写同样适用于排序节点的本地配置, 即orderer.yaml
中所能设置的. 例如ORDERER_KAFKA_RETRY_SHORTINTERVAL=1s
环境变量可以重写本地配置文件中的Orderer.Kafka.Retry.ShortInterval
.
Supported Kafka versions and upgrading
支持的 Kafka 版本和升级
Supported Kafka versions for v1 are 0.9
and 0.10
. (Hyperledger Fabric
uses the sarama client library <https://github.com/Shopify/sarama>
_
and vendors a version of it that supports Kafka 0.9 and 0.10.)
Fabric V1 支持的 Kafka 版本是 0.9
和 0.10
. (Hyperledger Fabric 使用代码库: sarama client library <https://github.com/Shopify/sarama>
_ 支持的 Kafka 版本是 0.9
和 0.10
)
Out of the box the Kafka version defaults to 0.9.0.1
. If you wish to use a
different supported version, specify a supported version using theKafka.Version
key in orderer.yaml
.
默认的 Kafka 版本是 0.9.0.1
. 如果你使用其他支持的版本, 修改 orderer.yaml
文件中的参数 Kafka.Version
.
The current supported Kafka versions are:
目前支持的 Kafka 版本是:
Version: 0.9.0.1
Version: 0.10.0.0
Version: 0.10.0.1
Version: 0.10.1.0
调试(Debugging)
Set General.LogLevel
to DEBUG
and Kafka.Verbose
in orderer.yaml
to true
.
设置 orderer.yaml
文件中 General.LogLevel
为 DEBUG
和 Kafka.Verbose
为 true
.
例子(Example)
Sample Docker Compose configuration files inline with the recommended settings
above can be found under the fabric/bddtests
directory. Look fordc-orderer-kafka-base.yml
and dc-orderer-kafka.yml
.
包含了推荐的设置的Docker Compose 配置文件示例能够在 fabric/bddtests
目录中找到. 包括 dc-orderer-kafka-base.yml
文件和 dc-orderer-kafka.yml
文件.
.. Licensed under Creative Commons Attribution 4.0 International License
https://creativecommons.org/licenses/by/4.0/