Hyperledger Fabric学习(五)Orderer排序服务

1、启动过程

  • 从本地配置文件和环境变量中读取配置信息,构建配置树结构
  • 配置日志级别
  • 配置go pprof服务
  • 配置gRPC监听服务,创建gRPC服务连接
  • 配置MSP结构
  • 初始化签名结构
  • 初始化账本管理器结构
    • 创建操作账本的工厂结构LedgerFactory;
    • 如果是首次执行,初始化系统管道,将系统管道信息接入区块中;
    • 初始化共识插件,共识插件负责跟后台的队列打交道;
    • 创建各个账本的管理器Manager结构,并且启动共识过程,这里会启动本地所有账本的共识过程,包括系统账本和普通交易账本。为了防止阻塞multiChain.Manager,启动的方式是协程调用;
  • 初始化gRPC服务端结构
  • 绑定gRPC服务并启动

2、共识插件启动过程(Kafka集群)

  • 创建Producer结构
  • 发送Connect消息给Kafka,检测Kafka是否在运行
  • 创建处理对应Kafka Topic下的Consumer结构
  • 配置从指定partition读取消息的PartitionConsumer结构
  • 不断从Kafka中读取消息,处理消息

3、排序后消息的处理

       当前收到消息数达到BatchSize.MaxMessageCount或消息尺寸过大,或者超时时间达到BatchTimeout,则发送分块消息TTC-X到Kafka;
       Kafka集群维护多个topic分区。Kafka通过共识算法来确保写入到分区后的消息的一致性。即一旦写入分区,任何Orderer节点看到的都是相同的消息队列;
       Orderer节点在启动后,默认对本地账本对应的Kafka分区数据进行监听,开启一个Kafka Consumer端不断从Kafka拉取新的消息,并对消息进行处理。满足一定策略下还会将消息打包为区块。比如收到分块消息TCC-X,或者配置交易的时候,Orderer节点会切分之前从Kafka中收到的消息为区块,记录到本地账本结构中;
       具体逻辑代码实现如下:

for {
  select {
    //链故障,需要退出
    case <-chain.haltChan:
    //从Kafka中消费消息发生错误
    case kafkaErr := <-chain.channelConsumer.Errors():
      select {
        //如果接收不到Kafka的错误信息,则关闭与Kafka的连接,稍后重连
        case <-chain.errorChan: 
        default:
           close(chain.errorChan)
      }
    //成功读取到Kafka消息,进行逻辑处理
    case in, ok := <-chain.channelConsumer.Messages():
      select {
        case <-chain.errorChan: 
           chain.errorChan = make(chan struct{})         
           default:
      }
      switch msg.Type.(type) {
        //Kafka连接消息,忽略
        case *ab.KafkaMessage_Connect:
        //TTC消息,打包现有的一批消息为区块
        case *ab.KafkaMessage_TimeToCut:
        //(需要核心处理)Fabric相关消息,包括配置更新,应用通道交易等
        case *ab.KafkaMessage_Regular:
          processRegular()  //主要是读取消息
      }
    //定期发送TTC消息到Kafka
    case <-timer:
  }
}

4、对外的服务

  • Broadcast()接口负责接收Client发送过来的已经收集到背书策略的交易提案;
  • Deliver()接口负责将打包好的区块信息发送给订阅了该通道的组织(Organizition)中的Peer Leader节点;

        内部工作流程图如下:
图片

发布了622 篇原创文章 · 获赞 150 · 访问量 31万+

猜你喜欢

转载自blog.csdn.net/feizaoSYUACM/article/details/104975135