Fabric 1.4源码分析 kafka共识机制

本文档主要介绍kafka共识机制流程。在查看文档之前可以先阅览raft共识流程以及orderer服务启动流程。

1. kafka 简介

Kafka是最初由Linkedin公司开发,是一个分布式、分区的、多副本的、多订阅者,基于zookeeper协调的分布式日志系统,一种高吞吐量的分布式发布订阅消息系统。kafka详细介绍可以参考这一篇博客。kafka介绍

2. kafka共识

kafka共识当中,每个orderer节点即是生产者Producer也是消费者Consumer,在具体设计当中,每个channel对应一个topic,并且为了保证顺序性,只设置了一个patition。(参见orderer启动初始化kafka共识代码afka.New(conf, metricsProvider, healthChecker, registrar)),关于kafka共识,这里推荐一篇博客,可以看看设计思路以及实现流程。The ABCs of Kafka in Hyperledger Fabric

实现共识算法需要实现的接口。

type Consenter interface {
    // 处理普通交易
    Order(env *cb.Envelope, configSeq uint64) error
    // 处理配置交易
    Configure(config *cb.Envelope, configSeq uint64) error
    WaitReady() error
}

而接口chain在Consenter接口基础上增加来部分接口

type Chain interface {
    Order(env *cb.Envelope, configSeq uint64) error
    Configure(config *cb.Envelope, configSeq uint64) error
    WaitReady() error
    Errored() <-chan struct{}
    // 分配资源
    Start()
    // 释放资源
    Halt()
    MigrationStatus() migration.Status
}

kafka共识实现代码路径为:orderer/consensus/kafka/chain.go;首先,在创建chain时会调用start()方法分配资源,在kafka共识中,会初始化生产者producer、消费者Consumer以及一些配置。后续重点通过源码来介绍producer和consumer模块实现以及kafka共识整个交易的流程,即主要介绍交易排序整个流程。在此基础上,解决个人的一些疑问。

3. 交易排序处理

3.1 orderer作为生产者

首先,当发送一个交易给orderer时,会调用orderer模块的broadcast()服务,其中会调用bh.ProcessMessage(msg, addr)方法根据交易类型调用不同的方法处理。

其中无论是配置交易还是普通交易都会调用chain.enqueue()方法,通过chain.producer.SendMessage(message)方法将交易写入kafka。从而orderer作为生产者角色功能就是将客户端发过来的交易写入kafka。再次强调一下,每个通道对应一个topic,每个topic只有一个patition。

func (chain *chainImpl) enqueue(kafkaMsg *ab.KafkaMessage) bool {
    logger.Debugf("[channel: %s] Enqueueing envelope...", chain.ChainID())
    select {
    case <-chain.startChan: // The Start phase has completed
        select {
        case <-chain.haltChan: // The chain has been halted, stop here
            logger.Warningf("[channel: %s] consenter for this channel has been halted", chain.ChainID())
            return false
        default: // The post path
            payload, err := utils.Marshal(kafkaMsg)
            if err != nil {
                logger.Errorf("[channel: %s] unable to marshal Kafka message because = %s", chain.ChainID(), err)
                return false
            }
            message := newProducerMessage(chain.channel, payload)
            if _, _, err = chain.producer.SendMessage(message); err != nil {
                logger.Errorf("[channel: %s] cannot enqueue envelope because = %s", chain.ChainID(), err)
                return false
            }
            logger.Debugf("[channel: %s] Envelope enqueued successfully", chain.ChainID())
            return true
        }
    default: // Not ready yet
        logger.Warningf("[channel: %s] Will not enqueue, consenter for this channel hasn't started yet", chain.ChainID())
        return false
    }
}

3.2 orderer作为消费者

orderer作为消费者的功能为:将kafka对应topic里面的交易打包成区块,并写入账本。

其中,在orderer创建对应chain的时候调用chain.start()。

func (chain *chainImpl) Start() {
    go startThread(chain)
}

kafka会开启协程go startThread(chain),其中会对kafka进行一系列初始化工作。最后会调用chain.processMessagesToBlocks()方法,生成对应区块。

func (chain *chainImpl) processMessagesToBlocks() ([]uint64, error) {
    ...
    for {
        select {
        ...
        case in, ok := <-chain.channelConsumer.Messages():
            ...
            switch msg.Type.(type) {
            ...
            case *ab.KafkaMessage_Regular:
                if err := chain.processRegular(msg.GetRegular(), in.Offset); err != nil {
                    logger.Warningf("[channel: %s] Error when processing incoming message of type REGULAR = %s", chain.ChainID(), err)
                    counts[indexProcessRegularError]++
                } else {
                    counts[indexProcessRegularPass]++
                }
            }
            ...
    }
}

其中,会对chain.processRegular(msg.GetRegular(), in.Offset)消息进行处理。

其中,会针对配置交易和普通交易进行分别处理。普通交易会调用chain.BlockCutter().Ordered(message)生成对应的batchs,配置交易会一个交易一个区块,直接调用chain.BlockCutter().Cut()生成batch。然后再生成区块、写入账本。

4. 问题思考

  1. kafka共识模式下动态更新系统通道配置添加orderer,是否就可提供排序服务。
    经查看代码,在orderer启动过程中,只有raft共识会判断该orderer(raft节点)是否在对应对consenter集群中。如果不在则会创建inactivechain,无法提供排序服务(必须更新consenter才行)。但是kafka不存在上述过程,在orderer启动后,会从kafka同步系统通道区块,当区块包括创建通道交易时,会创建应用通道,同步应用通道区块(该流程类似raft共识写账本流程)。因此,该orderer可以提供服务,但是如果是每个组织提供orderer的场景、由于没有更新应用通道排序组织,从而导致无法通过服务发现获取该orderer信息。

菜鸟学习Fabric源码学习 — kafka共识机制的更多相关文章

  1. 菜鸟系列Fabric源码学习—orderer服务启动

    Fabric 1.4 orderer 服务启动流程 1.提要 orderer提供broadcast和deliver两个服务接口.orderer节点与各个peer节点通过grpc连接,orderer将所 ...

  2. 菜鸟系列Fabric源码学习 — 区块同步

    Fabric 1.4 源码分析 区块同步 本文主要从源码层面介绍fabric peer同步区块过程,peer同步区块主要有2个过程: 1)peer组织的leader与orderer同步区块 2)pee ...

  3. 菜鸟系列Fabric源码学习 — peer节点启动

    Fabric 1.4 源码分析peer节点启动 peer模块采用cobra库来实现cli命令. Cobra提供简单的接口来创建强大的现代化CLI接口,比如git与go工具.Cobra同时也是一个程序, ...

  4. 菜鸟系列Fabric源码学习—创建通道

    通道创建源码解析 1. 与通道创建相关配置及操作命令 主要是configtx.yaml.通过应用通道的profile生成创建通道的配置文件. TwoOrgsChannel: Consortium: S ...

  5. 菜鸟系列Fabric源码学习 — committer记账节点

    Fabric 1.4 源码分析 committer记账节点 本文档主要介绍committer记账节点如何初始化的以及committer记账节点的功能及其实现. 1. 简介 记账节点负责验证交易和提交账 ...

  6. 菜鸟系列Fabric源码学习 — MVCC验证

    Fabric 1.4 源码分析 MVCC验证 读本节文档之前建议先查看[Fabric 1.4 源码分析 committer记账节点]章节. 1. MVCC简介 Multi-Version Concur ...

  7. 菜鸟学习Fabric源码学习 — Endorser背书节点

    Fabric 1.4 源码分析 Endorser背书节点 本文档主要介绍fabric背书节点的主要功能及其实现. 1. 简介 Endorser节点是peer节点所扮演的一种角色,在peer启动时会创建 ...

  8. 菜鸟学习Fabric源码学习 — 背书节点和链码容器交互

    Fabric 1.4 源码分析 背书节点和链码容器交互 本文档主要介绍背书节点和链码容器交互流程,在Endorser背书节点章节中,无论是deploy.upgrade或者调用链码,最后都会调用Chai ...

  9. 菜鸟的jQuery源码学习笔记(前言)

    前言 相信任何一名前端开发人员或者是前端爱好者都对jQuery不陌生.jQuery简单易用,功能强大,特别是拥有良好的浏览器兼容性,大大降低了前端开发的难度,使得前端开发变得“平易近人起来”.自从本人 ...

随机推荐

  1. java 类加载器的委托机制

    l 当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢? 1.首先当前线程的类加载器去加载线程中的第一个类. 2.如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B. 3 ...

  2. java 注解(Annotation)

    注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记. 以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就 ...

  3. CCPC2018 桂林 G "Greatest Common Divisor"(数学)

    UPC备战省赛组队训练赛第十七场 with zyd,mxl G: Greatest Common Divisor 题目描述 There is an array of length n, contain ...

  4. P1008 对齐输出

    题目描述 读入三个整数,按每个整数占8个字符的宽度,右对齐输出它们. 输入格式 输入的一行包含三个整数 \(a,b,c(1 \le a,b,c \le 10^6)\) . 输出格式 输出一行包含三个整 ...

  5. ZR1158

    ZR1158 http://www.zhengruioi.com/contest/446/problem/1158 给定限制的问题大多数都是容斥或者二分,或者二分之后容斥 首先,这个问题的第一步我们还 ...

  6. eslint在webstorm中有错误警告

    1. 报错Missing space before function parentheses的问题 解决:在代码目录中,打开.eslint文件,并在rules中添加如下一行代码即可: "sp ...

  7. [转载]sublime用法精华

    Sublime Text 全程指南 九月 03.2015. 暂无评论 永远站 作者:Lucida 原文链接:http://lucida.me/blog/sublime-text-complete-gu ...

  8. CF 453C. Little Pony and Summer Sun Celebration

    CF 453C. Little Pony and Summer Sun Celebration 构造题. 题目大意,给定一个无向图,每个点必须被指定的奇数或者偶数次,求一条满足条件的路径(长度不超\( ...

  9. XSS攻击及防范

    1.什么是XSS攻击 跨站脚本攻击(Cross Site Scripting),攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到 ...

  10. C#面试题整理2(带答案)

    一.C# 理论 1.1.简述 private. protected. public. internal.protected internal 访问修饰符和访问权限 private : 私有成员, 在类 ...