Hyperledger Fabric 排序節點處理 Broadcast 請求的實現

來源:互聯網
上載者:User

Hyperledger 源碼分析之 Fabric

Broadcast,意味著用戶端將請求訊息(例如完成背書後的交易)通過 gRPC 介面發送給 Ordering 服務。

這些請求訊息,會交給 orderer.common.server 包中 server 結構體的 Broadcast(srv ab.AtomicBroadcast_BroadcastServer) error 方法處理。該方法主要會調用到 orderer.common.broadcast 包中 handlerImpl 結構的 Handle(srv ab.AtomicBroadcast_BroadcastServer) error 方法進行處理。

handlerImpl 結構體十分重要,完成對 Broadcast 請求的處理過程。

type handlerImpl struct {    sm ChannelSupportRegistrar}func (bh *handlerImpl) Handle(srv ab.AtomicBroadcast_BroadcastServer) error

Handle(srv ab.AtomicBroadcast_BroadcastServer) error 方法會開啟一個迴圈來從 srv 中讀取請求訊息並進行處理,直到結束。核心代碼如下所示。

for {    msg, error := srv.Recv() // 從請求中提取一個 Envelope 訊息    chdr, isConfig, processor, err := bh.sm.BroadcastChannelSupport(msg) // 解析訊息:是否為配置訊息,訊息應由哪個鏈處理      // 對應的鏈對訊息進行處理    if !isConfig {        configSeq, err := processor.ProcessNormalMsg(msg) //訊息檢查        processor.Order(msg, configSeq) //入隊列操作    } else {        config, configSeq, err := processor.ProcessConfigUpdateMsg(msg) // 合并配置更新訊息        processor.Configure(config, configSeq) //入隊列操作    }    srv.Send(&ab.BroadcastResponse{Status: cb.Status_SUCCESS}) // 返迴響應訊息}

Broadcast 請求的整體處理過程如下圖所示。

解析訊息

首先,解析訊息,擷取訊息頭、是否為配置訊息、擷取對應處理器結構(鏈結構)。

chdr, isConfig, processor, err := bh.sm.BroadcastChannelSupport(msg)

實際上,會映射到 orderer.common.server 包中 broadcastSupport 結構體的 BroadcastChannelSupport(msg *cb.Envelope) (*cb.ChannelHeader, bool, broadcast.ChannelSupport, error) 方法,進一步調用到 orderer.common.multichannel 包中 Registrar 結構體的對應方法。

func (r *Registrar) BroadcastChannelSupport(msg *cb.Envelope) (*cb.ChannelHeader, bool, *ChainSupport, error) {    chdr, err := utils.ChannelHeader(msg)    if err != nil {        return nil, false, nil, fmt.Errorf("could not determine channel ID: %s", err)    }    cs, ok := r.chains[chdr.ChannelId] //應用通道、系統通道    if !ok {        cs = r.systemChannel    }    isConfig := false    switch cs.ClassifyMsg(chdr) {    case msgprocessor.ConfigUpdateMsg:        isConfig = true    default:    }    return chdr, isConfig, cs, nil}

channel 頭部從訊息信封結構中解析出來;是否為配置資訊根據訊息頭中類型進行判斷(是否為 cb.HeaderType_CONFIG_UPDATE);通過字典查到對應的 ChainSupport 結構(應用通道、系統通道)作為處理器。

之後,利用解析後的結果,分別對不同類型的訊息(普通訊息、配置訊息)進行不同處理。下面以應用通道的 ChainSupport 結構作為處理器進行介紹。 處理非配置訊息

對於非配置訊息,主要執行如下兩個操作:訊息檢查和入隊列操作。

configSeq, err := processor.ProcessNormalMsg(msg) //訊息檢查processor.Order(msg, configSeq) //入隊列操作

訊息檢查方法會映射到 orderer.common.msgprocessor 包中 StandardChannel 結構體的 ProcessNormalMsg(env *cb.Envelope) (configSeq uint64, err error) 方法,實現如下。

func (s *StandardChannel) ProcessNormalMsg(env *cb.Envelope) (configSeq uint64, err error) {    configSeq = s.support.Sequence() // 擷取配置的序號,映射到 common.configtx 包中 configManager 結構體的對應方法    err = s.filters.Apply(env) // 進行過濾檢查,實現為 orderer.common.msgprocessor 包中 RuleSet 結構體的對應方法。    return}

其中,過濾器會在建立 ChainSupport 結構時候初始化:

應用通道:orderer.common.mspprocessor 包中的 CreateStandardChannelFilters(filterSupport channelconfig.Resources) *RuleSet 方法,包括 EmptyRejectRule、SizeFilter 和 SigFilter(ChannelWriters 角色)。

系統通道:orderer.common.mspprocessor 包中的 CreateSystemChannelFilters(chainCreator ChainCreator, ledgerResources channelconfig.Resources) *RuleSet 方法,包括 EmptyRejectRule、SizeFilter、SigFilter(ChannelWriters 角色)和 SystemChannelFilter。

入隊列操作會根據 consensus 配置的不同映射到 orderer.consensus.solo 包或 orderer.consensus.kafka 包中的方法。

以 kafka 情況為例,會映射到 chainImpl 結構體的對應方法。該方法會將訊息進一步封裝為 sarama.ProducerMessage 類型訊息,通過 enqueue 方法發給 Kafka 後端。

func (chain *chainImpl) Order(env *cb.Envelope, configSeq uint64) error {    marshaledEnv, err := utils.Marshal(env)    if err != nil {        return fmt.Errorf("cannot enqueue, unable to marshal envelope because = %s", err)    }    if !chain.enqueue(newNormalMessage(marshaledEnv, configSeq)) {        return fmt.Errorf("cannot enqueue")    }    return nil}
處理配置訊息

對於配置訊息,處理過程與正常訊息略有不同,包括合并配置更新訊息和入隊列操作。

config, configSeq, err := processor.ProcessConfigUpdateMsg(msg) // 合并配置更新訊息processor.Configure(config, configSeq) //入隊列操作

合并配置更新訊息方法會映射到 orderer.common.msgprocessor 包中 StandardChannel 結構體的 ProcessConfigUpdateMsg(env *cb.Envelope) (configSeq uint64, err error) 方法,計算合并後的配置和配置編號,實現如下。

func (s *StandardChannel) ProcessConfigUpdateMsg(env *cb.Envelope) (config *

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.