Hyperledger Fabric release1.1 基于Kafka的排序服务相关配置

Hyperledger Fabric release1.1 基于Kafka的排序服务相关配置_第1张图片

概览

当排序节点通过RPC广播(Broadcast)接收到交易时 ,它会检查广播交易的客户端是否有权限去修改通道(channel)数据,然后将这些交易分发到Kafka适当的分区(partition)中。

每一个通道(channel)在Kafka中被映射到一个单独的单分区(partition)主题(topic)。 在这里 topic 与 partition 二者是一对一的关系

该分区也被排序节点所消费(consume),排序节点将接收到的交易分组写入到本地区块,将其保留在本地账本中,并通过Deliver RPC提供给需要接收的客户端。

在这个过程中orderer节点充当了 "生产者" 和 "消费者" 两个角色

  • 生产者:对发送者的权限进行检查,之后发送给Kafka中对应通道(channel)的主题(Topic)分区(partition)
  • 消费者: 实时监听消息,并对消息进行后续处理,生成区块或者分割交易。

Orderer主要包含两个接口 :
Broadcast: 客户端发送交易请求到排序服务进行排序处理。
Deliver:客户端或者Peer从排序服务获取排序后的区块。

Kafka相关的配置信息解析

大写的字母表示的是yaml文件中environment部分的内容。
xxx.yyy.zzz这种表示方式是按照yaml格式的层级关系

Kafka集群的节点数量最少为4个,这样就可以容忍一个节点宕机。所有的通道能够继续读写,也可以创建新的通道。

ZooKeeper集群的节点数量可以是3、5或者7。它必须是一个奇数来避免分裂(split-brain)情景,大于1以避免单点故障。 超过7个ZooKeeper服务器则被认为是多余的。

Orderer相关配置

Kafka 相关信息被写在网络的初始区块中. 如果你使用 configtxgen 工具, 编辑 configtx.yaml 文件– 或者挑一个现成的系统通道的初始区块配置文件。

Orderer.OrdererType:指定排序服务的类型Kafka
Orderer.BatchTimeout: 设置区块最长的时间间隔
Orderer.BatchSize. MaxMessageCount: 设定每个区块可以包含的最大交易数量
Orderer.BatchSize. PreferredMaxBytes:首选的区块大小

通过参数Orderer.Batchsize.PreferredMaxBytes设置首选的区块大小. Kafka 处理相对较小的信息有更高的吞吐量; 针对小于 1 MiB 大小的值

Orderer.BatchSize.AbsoluteMaxBytes: 设定区块的最大容量,不包含区块头。(会影响Kafka. Brokers的配置)
Orderer. Addresses:IP:Port的格式
Orderer.Kafka.Brokers:这是一个 Kafka的seed Brokers列表。里面至少要包含两个seed。
General.GenesisFile或者ORDERER_GENERAL_GENESISFILE:指定初始区块(genesis.block)的位置

例如如下配置内容:

Orderer: &OrdererDefaults

    OrdererType: kafka

    Addresses:
        - orderer.example.com:7050

    BatchTimeout: 2s

    BatchSize:
        MaxMessageCount: 10
        AbsoluteMaxBytes: 98 MB
        PreferredMaxBytes: 512 KB

    Kafka:
        Brokers:
            - kafka0:9092
            - kafka1:9092
            - kafka2:9092
            - kafka3:9092

使用 configtxgen 工具 创建初始区块. 设置是全局的设置, 也就是说这些设置的生效范围是网络中所有的排序节点. 记录下初始区块的位置.

channel创建时orderer与Kafka的交互过程

ORDERER_KAFKA_RETRY_SHORTINTERVAL=1s:轮询间隔
ORDERER_KAFKA_RETRY_SHORTTOTAL=30s:超时时间

Kafka.Retry 区域让你能够调整metadata/producer/consumer请求的频率以及socket的超时时间. (这些应该就是所有在 kafka 的生产者和消费者 中你需要的设置)

当一个 channel 被创建, 或当一个现有的 channel 被重新读取(刚启动 orderer 的情况), orderer 通过以下方式和 Kafka 集群进行交互

  • 为 channel 对应的 Kafka 分区 创建一个 Kafka 生产者
  • 通过生产者向这个分区发一个空的连接信息
  • 为这个分区创建一个 Kafka 消费者.
  • 如果任意步骤出错, 你可以调整其重复的频率.

这些步骤会在每一个Kafka.Retry.ShortInterval指定的时间间隔后进行重试 Kafka.Retry.ShortTotal次.
再以Kafka.Retry.LongInterval规定的时间间隔重试 Kafka.Retry.LongTotal次直到成功.

需要注意的是 orderer 不能读写该 channel 的数据直到所有上述步骤都成功执行.

Kafka相关配置

适当配置你的Kafka集群. 确保每一个Kafka节点都配置了以下的值

KAFKA_UNCLEAN_LEADER_ELECTION_ENABLE=false

数据一致性是区块链环境的关键. 我们不能选择不在同步副本集中的channel leader, 也不能冒风险去覆盖前一leader所产生的偏移量, 那样的结果就是重写orderers所产生的区块链数据. 所以设置为false

KAFKA_DEFAULT_REPLICATION_FACTOR = N (N是一个待设定的数字)。

N 的值应该小于Kafka集群的数量。
参数 N 表示每个channel的数据会复制到 N 个 broker 中. 这些是 channel同步副本集的候选. 不是所有 broker 都需要是随时可用的. N 值需要设置为绝对小于 Kafka集群的数量 , 因为channel的创建需要不少于 N 个broker是启动的. 所以如果设置 N = Kafka集群的节点数量 , 一个 broker 宕机就意味着区块链网络不能再创建channel. 那么故障容错的排序服务也就不存在了.

KAFKA_MIN_INSYNC_REPLICAS = M (M是一个待设定的数字)。

M 的值要大于 1 小于 N 。
数据至少复制到 M 个副本中,才被认为是有效同步。
如果 N - M 个设备宕机。还是可以正常工作。
如果可访问的数量小于M个, 则它会停止接受写入操作. 读操作可以正常运行. 当M个副本重新同步后,通道就可以再次变为可写入状态.

注意这个 M 和 N 的最小值是 2 和 3 。因为 Kafka集群的节点最小数量为 4 个。 1 < M < N < 4。

KAFKA_MESSAGE_MAX_BYTES : 消息的最大字节数

如果Orderer.BatchSize.AbsoluteMaxBytes 的值设置为98。
则可将KAFKA_MESSAGE_MAX_BYTES的值设置为99 * 1024 * 1024
KAFKA_REPLICA_FETCH_MAX_BYTES的值也设置为99 * 1024 * 1024

KAFKA_REPLICA_FETCH_MAX_BYTES :

KAFKA_MESSAGE_MAX_BYTESKAFKA_REPLICA_FETCH_MAX_BYTES 的值需要大于 Orderer.BatchSize.AbsoluteMaxBytes 的值. 再为区块头增加一些余量 -- 1 MiB 就足够了. 需要满足以下条件:
KAFKA_MESSAGE_MAX_BYTES 需要严格小于 socket.request.max.bytes , 这个值默认是100Mib。(如果你希望区块大于100MiB, 你需要去修改硬代码中的变量 brokerConfig.Producer.MaxMessageBytes , 代码位置是 fabric/orderer/kafka/config.go , 再重新编译代码, 不建议这么做)

services:
  zookeeper:
    image: hyperledger/fabric-zookeeper
    restart: always
    ports:
      - '2181'
      - '2888'
      - '3888'

  kafka:
    image: hyperledger/fabric-kafka
    restart: always
    environment:

      - KAFKA_MESSAGE_MAX_BYTES=103809024 # 99 * 1024 * 1024 B
      - KAFKA_REPLICA_FETCH_MAX_BYTES=103809024 # 99 * 1024 * 1024 B
      - KAFKA_UNCLEAN_LEADER_ELECTION_ENABLE=false

    ports:
      - '9092'

  orderer.example.com:
    container_name: orderer.example.com
    image: hyperledger/fabric-orderer
    environment:
      - ORDERER_KAFKA_RETRY_SHORTINTERVAL=1s
      - ORDERER_KAFKA_RETRY_SHORTTOTAL=30s
      - ORDERER_KAFKA_VERBOSE=true   
    ports:
      - 7050:7050
  kafka0:
    container_name: kafka0
    extends:
      file: base/docker-compose-base.yaml
      service: kafka
    environment:
      - KAFKA_BROKER_ID=0
      - KAFKA_MIN_INSYNC_REPLICAS=2
      - KAFKA_DEFAULT_REPLICATION_FACTOR=3
      - KAFKA_ZOOKEEPER_CONNECT=zookeeper0:2181,zookeeper1:2181,zookeeper2:2181
    depends_on:
      - zookeeper0
      - zookeeper1
      - zookeeper2

  kafka1:
    container_name: kafka1
    extends:
      file: base/docker-compose-base.yaml
      service: kafka
    environment:
      - KAFKA_BROKER_ID=1
      - KAFKA_MIN_INSYNC_REPLICAS=2
      - KAFKA_DEFAULT_REPLICATION_FACTOR=3
      - KAFKA_ZOOKEEPER_CONNECT=zookeeper0:2181,zookeeper1:2181,zookeeper2:2181
    depends_on:
      - zookeeper0
      - zookeeper1
      - zookeeper2

  kafka2:
    container_name: kafka2
    extends:
      file: base/docker-compose-base.yaml
      service: kafka
    environment:
      - KAFKA_BROKER_ID=2
      - KAFKA_MIN_INSYNC_REPLICAS=2
      - KAFKA_DEFAULT_REPLICATION_FACTOR=3
      - KAFKA_ZOOKEEPER_CONNECT=zookeeper0:2181,zookeeper1:2181,zookeeper2:2181
    depends_on:
      - zookeeper0
      - zookeeper1
      - zookeeper2

  kafka3:
    container_name: kafka3
    extends:
      file: base/docker-compose-base.yaml
      service: kafka
    environment:
      - KAFKA_BROKER_ID=3
      - KAFKA_MIN_INSYNC_REPLICAS=2
      - KAFKA_DEFAULT_REPLICATION_FACTOR=3
      - KAFKA_ZOOKEEPER_CONNECT=zookeeper0:2181,zookeeper1:2181,zookeeper2:2181
    depends_on:
      - zookeeper0
      - zookeeper1
      - zookeeper2

  orderer.example.com:
    extends:
      file:   base/docker-compose-base.yaml
      service: orderer.example.com
    container_name: orderer.example.com
    depends_on:
      - zookeeper0
      - zookeeper1
      - zookeeper2
      - kafka0
      - kafka1
      - kafka2
      - kafka3

调试

设置 orderer.yaml文件中 General.LogLevelDEBUGKafka.Verbosetrue

建议以及注意事项

你可以使用环境变量重写设置.
你能够通过设置环境变量来重写 Kafka节点和Zookeeper服务器的设置.
替换配置参数中的 点 为 下划线 – 例如:KAFKA_UNCLEAN_LEADER_ELECTION_ENABLE=false 环境变量重写配置参数 unclean.leader.election.enable.
环境变量重写同样适用于排序节点的本地配置, 即 orderer.yaml中所能设置的. 例如 ORDERER_KAFKA_RETRY_SHORTINTERVAL=1s 环境变量可以重写本地配置文件中的Orderer.Kafka.Retry.ShortInterval.

启动环境时,建议按照以下顺序启动:ZooKeeper 集群, Kafka 集群, 排序节点

你可能感兴趣的:(Hyperledger Fabric release1.1 基于Kafka的排序服务相关配置)