hyperledger fabric pbft算法架构的简要解析

fabric的共识算法代码全部都在consensus文件夹里,consensus文件夹里主要分为controller,executor,helper,noops,pbft,util文件模块。
其中consensus.Go 主要包含了算法插件内部对外部暴露的接口和hyperledger外部对算法内部暴露的接口。

  • controller:共识算法模块是可插拔的,在controller里面可以选择具体使用哪种共识算法。目前hyperledger它提供了一个pbft算法和一个比较简单的noops算法。
  • executor:executor和helper是两个相互依赖的模块,主要提供了共识算法和外部衔接的一块代码。主要负责事件处理的转接。
  • helper:这里面主要包含了对外部接口的一个调用,比如执行处理transaction,stateupdate,持久化一些对象等。
  • noops: noops也是一种比较简单共识算法
  • pbft: pbft算法,下面会简单的介绍一下pbft算法的调用流程。
  • util: 一些交互需要的工具包,最主要的一个实现的功能就是它的消息机制。

下面简要介绍两点,一点pbft算法代码内部从头到尾的一个调用流程,一点是pbft算法内部的事件机制和timeout代码的一个简要解析。

内部调用流程

在engine.go里面有获取一个共识算法plugin

func GetEngine(coord peer.MessageHandlerCoordinator) (peer.Engine, error) {var err errorengineOnce.Do(func() {engine = new(EngineImpl)engine.helper = NewHelper(coord)engine.consenter = controller.NewConsenter(engine.helper)engine.helper.setConsenter(engine.consenter)engine.peerEndpoint, err = coord.GetPeerEndpoint()engine.consensusFan = util.NewMessageFan()go func() {logger.Debug("Starting up message thread for consenter")// The channel never closes, so this should never breakfor msg := range engine.consensusFan.GetOutChannel() {engine.consenter.RecvMsg(msg.Msg, msg.Sender)}}()})return engine, err
}

它初始化一个consenter和一个helper,并互相把一个句柄赋值给了对方。这样做的目的,就是为了可以让外部调用内部,内部可以调用外部。

首先看一下它是如何初始化一个共识模块的:

 1. 调用controller获取一个plugin,当选择是pbft算法时,它会调用pbft.go 里的 GetPlugin(c consensus.Stack)方法,在pbft.go里面把所有的外部参数读进算法内部。
func New(stack consensus.Stack) consensus.Consenter {handle, _, _ := stack.GetNetworkHandles()id, _ := getValidatorID(handle)switch strings.ToLower(config.GetString("general.mode")) {case "batch":return newObcBatch(id, config, stack)default:panic(fmt.Errorf("Invalid PBFT mode: %s", config.GetString("general.mode")))}
}
 2. 用方法newObcBatch(id uint64, config *viper.Viper, stack consensus.Stack)初始化一个obcbatch对象。这个batch对象的作用就是用来做request缓存,提高transaction的执行效率,如果每来一个请求就去做一次共识,那代价会很高。缓存存储在batchStore里。3. 在newobcbatch时,会初始化得到一个pbftcore的一个实例,这个是算法的核心模块。并此时会启动一个batchTimer(这个batchTimer是一个计时器,当batchTimer timeout后会触发一个sendbatch操作,这个只有primary节点才会去做)。当然此时会创建一个事件处理机制,这个事件处理机制是各个模块沟通的一个bridge。4. 在初始化pbftcore时,在把所用配置读进的同时,创建了三个timer
instance.newViewTimer = etf.CreateTimer()
instance.vcResendTimer = etf.CreateTimer()
instance.nullRequestTimer = etf.CreateTimer()
  • newViewTimer对应于viewChangeTimerEvent{},当这个timer在一定时间没有close时,就会触发一个viewchange事件。
  • vcResendTimer对应viewChangeResendTimerEvent,发出viewchange过时时会触发一个将viewchange从新发送。
  • nullRequestTimer对应nullRequestEvent,如果主节点长期没有发送preprepare消息,也就是分配了seq的reqBatch。它timeout就认为主节点挂掉了然后发送viewchange消息。

当然理解以上东西需要了解pbft算法的各个具体流程。以上是pbft算法插件的初始化流程, 并讲解了部分初始化我认为比较重要的信息。具体初始化需要看代码了。

算法内部的事件机制

为什么要把事件机制单独提出来,因为要想完全看懂它的调用流程,就必须理解它的事件流。说起来它的事件流真是复杂,我觉得可以不必要这么复杂。

它有两个事件流,一个是在helper里,一个是在batch里。

首先分析一下它的事件流工具,它整个代码都在util包里的events.go,我认为这个设计还是棒棒哒,在我自己的共识算法测试环境里,对它改装了一下,感觉还是不错的。

首先看一下它提供的接口

type Manager interface {Inject(Event)   // A temporary interface to allow the event manager thread to skip the queueQueue() chan<- Event // Get a write-only reference to the queue, to submit eventsSetReceiver(Receiver) // Set the target to route events toStart()              // Starts the Manager thread TODO, these thread management things should probably go awayHalt()                // Stops the Manager thread
}

SetReceiver(Receiver)是一个很重要的接口,决定了这个事件机制的灵活性。考验我表达能力的时候到了~~,一个事件机制必定有一个输入和一个输出,这个SetReceiver(Receiver) interface 方法就决定了事件流的去向。下面是receiver的interface,凡是事件的接受者都必须实现ProcessEvent(e Event) Event方法。batch里面实现了此方法。

type Receiver interface {// ProcessEvent delivers an event to the Receiver, if it returns non-nil, the return is the next processed eventProcessEvent(e Event) Event
}

那对应的输出,Queue() chan<- Event ,它返回一个event channel,你所有的消息尽管往里面发。接收者取决于receiver。

func SendEvent(receiver Receiver, event Event) {next := eventfor {// If an event returns something non-nil, then process it as a new eventnext = receiver.ProcessEvent(next)if next == nil {break}}
}

这段代码是把事件传给receiver处理。举个batch事件流机制的例子。

在external.go里面实现了接收外边request请求的接口。在obcbatch初始化会对其创建并且把event manager复制给externalEventReceiver。因此所有接收到这个manager的消息都会进入到batch里面。

// RecvMsg is called by the stack when a new message is received
func (eer *externalEventReceiver) RecvMsg(ocMsg *pb.Message, senderHandle *pb.PeerID) error {eer.manager.Queue() <- batchMessageEvent{msg:    ocMsg,sender: senderHandle,}return nil
}

当接收到一个request时,将batchMessageEvent放到事件流,之后

func (em *managerImpl) eventLoop() {for {select {case next := <-em.events:em.Inject(next)case <-em.exit:logger.Debug("eventLoop told to exit")return}}
}

这个死循环接收到的event 进行了em.Inject(next),并执行

func SendEvent(receiver Receiver, event Event) {next := eventfor {// If an event returns something non-nil, then process it as a new eventnext = receiver.ProcessEvent(next)if next == nil {break}}
}

之后在obcbatch ProcessEvent里执行了这个操作

case batchMessageEvent:ocMsg := etreturn op.processMessage(ocMsg.msg, ocMsg.sender)

这是消息往里抛的过程,同理,消息往外抛,就是算法内部把event抛给外部executor的event manager。

Timer机制

timer机制和event机制有很大关联,time out后,会把事先创建的event塞到eventmanager里的事件流里。

type Timer interface {SoftReset(duration time.Duration, event Event) // start a new countdown, only if one is not already startedReset(duration time.Duration, event Event)     // start a new countdown, clear any pending eventsStop()                                         // stop the countdown, clear any pending eventsHalt()                                         // Stops the Timer thread
}

设置time out主要是SoftReset和reset方法。因此在初始化,会把Manager传给Timer。

但这样的事件机制在大数据处理时,可能会出现问题。

hyperledger fabric PBFT算法简要解析相关推荐

  1. HyperLedger Fabric共识算法

    当前在联盟链的应用场景中,使用的共识算法有3种:SOLO.Kafka和PBFT(拜占庭容错). Solo模式 在Hyperledger Fabric中的solo模式的共识算法,是最简单的一种共识算法, ...

  2. 浅析Hyperledger Fabric共识算法

    链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载. 区块链系统是一个分布式架构,交易账本信息由各个节点管理,组成一个庞大的分布式账本.在分布式系统中,各个节点收到的交易信息 ...

  3. hyperledger fabric 交易结构以及解析

    Fabric 1.0源代码分析(43) Tx(Transaction 交易)_yinchengmvp的技术博客_51CTO博客 Hyperledger Fabric的区块结构 交易结构Hyperled ...

  4. 在 Hyperledger Fabric v1.4 下添加 PBFT 共识算法

    在文章的开篇,首先对如下两篇文章的博主表示感谢,感谢他们对学习资源的共享. https://www.yezhem.com/index.php/archives/52/ https://blog.csd ...

  5. Hyperledger Fabric相关文件解析

    1相关文件说明 这一部分涉及相关配置文件的解析, 网络的启动涉及到多个文件,本文按以下顺序进行分析: . ├── base │ ├── docker-compose-base.yaml #1 │ └─ ...

  6. Fabric学习笔记-PBFT算法

    本文介绍了实用拜占庭容错算法(PBFT). Fabric在v0.6中采用的是PBFT算法,在v1.0.0-preview中是SBFT算法,在v1.0.0-release中文档上说PBFT还在开发中,项 ...

  7. Hyperledger Fabric无排序组织以Raft共识算法启动多个Orderer服务、多组织共同运行维护Orderer服务

    前言 在Hyperledger Fabric无系统通道启动及通道的创建和删除中,我们已经完成了以无系统通道的方式启动 Hyperledger Fabric 网络,并将链码安装到指定通道.但目前为止,实 ...

  8. Hyperledger Fabric 2.0 官方文档中文版 第3章 关键概念

    Hyperledger Fabric 2.0 官方文档中文版 第3章 关键概念 总目录 3.关键概念 引言 什么是区块链? 区块链为什么有用? 什么是Hyperledger Fabric? Hyper ...

  9. (转)HyperLedger Fabric协议规范

    HyperLedger Fabric协议规范 协议规范 前言 这份文档是带有权限的区块链的工业界实现的协议规范.它不会详细的解释实现细节,而是描述系统和应用之间的接口和关系. 目标读者 这份规范的目标 ...

  10. 以太坊和Hyperledger Fabric之间的差异

    在这篇文章中,我们将介绍区块链中两个主要平台之间的差异:以太坊和Hyperledger.如果你正在考虑在项目中使用哪一个.这个博客的亮点是希望帮助你做出决定.但在我们详细说明之前,我们先来看一些定义. ...

最新文章

  1. 堆(heap)与栈(stack)的区别(二)
  2. eclipse中搭建ssm框架
  3. 今日头条技术架构到底有多牛?
  4. 如何成为一名大数据工程师?
  5. PYTHON自动化Day4-交换变量,字符串方法,拷贝,集合,文件,文件指针
  6. 世界首个!AI农作物病害检测竞赛火热进行中 | AI Challenger 全球AI挑战赛
  7. 如果你忘记了DotnetNuke站点的host和admin密码,解决方案
  8. java 用mysql游标_MySQL游标
  9. VC第三方界面库xtremetoolkitPro使用说明
  10. 震旦ad369s_震旦ad369s驱动
  11. 公众号写作排版指南v2.0(适配Dark Mode)
  12. 实现表格隔行变色研究
  13. error obtaining controller instance: failed to create NAT chain
  14. 大规模知识图谱数据存储实战解析
  15. 沈向洋回归,从微软独立的小冰要弯道超车了
  16. 程序员用代码求救 同事“秒懂”
  17. Rational Rose2007的安装
  18. Hudi on Flink在顺丰的实践应用.ppt
  19. Word中插入手写体签名
  20. OpenCV库中watershed函数(分水岭算法)的详细使用例程

热门文章

  1. 支持多浏览器的js拖拽 (转domkey0303 的blog)
  2. instead of触发器实现复杂视图dml和应用逻辑
  3. 2. 知识图谱-命名实体识别(NER)详解
  4. CSS3 transform 属性
  5. ABAP-内表数据下载到CSV格式(原创转载请注明)
  6. 字符串反转的进一步应用----单词反转
  7. 利用TreeView控件动态生成无限级树(续:通过绑定动态xml文件)(转)
  8. DDMF PluginDoctor Mac - 插件分析器音频质量测试
  9. iOS底层探索之多线程(二)—线程和锁
  10. 怎样才能打开Tuxera NTFS的主界面?