超級賬本fabric原理之gossip詳解


Goosip協議

去中心化、容錯和最終一致性的算法
信息達到同步的最優時間:log(N)。

功能
節點發現
數據廣播

gossip中有三種基本的操作:

  • push - A節點將數據(key,value,version)及對應的版本號推送給B節點,B節點更新A中比自己新的數據
  • pull - A僅將數據key,version推送給B,B將本地比A新的數據(Key,value,version)推送給A,A更新本地
  • push/pull - 與pull類似,只是多了一步,A再將本地比B新的數據推送給B,B更新本地

說到底,gossip服務是處理消息的,每種類型的消息有不同的用途

消息類型

gossip服務使用不同模塊處理不同類型的消息。消息類型原型在/protos/message.proto中定義。gossip中傳播的消息以GossipMessage形式傳遞,具體的消息數據存放在GossipMessage中的Content成員中。

節點關系消息

與頻道成員身份、關系和存續相關的消息類型。
AliveMessage - alive消息
MembershipRequest - 成員關系請求消息
MembershipResponse -成員關系應答消息

pull機制消息

pull進來的可以是以塊數據為內容的消息,也可以是身份數據為內容的消息,下述4種消息中都有一個成員MsgType來表明這個消息中所攜帶的數據內容。從pull步驟上分為四種:
GossipHello - hello消息
DataDigest - 消息摘要
DataRequest - 摘要請求
DataUpdate - 摘要應答

state消息

和狀態有關的消息。這里的狀態指的是chain的數據狀態,如一個結點所存儲的塊數據是否一致,可以說這里所謂的狀態接近數據的意思。
StateInfo - 狀態消息
DataMessage - 數據消息(block)
TransactionMessage - 交易數據;

輔助類消息

這類消息不承擔具體傳送傳播數據的任務,而是輔助性的:
Empty - 空消息,用於結點間的Ping(來測試結點是否連通)和測試。
ConnEstablish - 用於gossip之間的握手,即任何時候一個peer想與另一個peer連接通信,都需要先發送這個消息以證明其身份。

gossip模塊

主要功能

gossip部分接口

type Gossip interface {
	// Send sends a message to remote peers
	Send(msg *proto.GossipMessage, peers ...*comm.RemotePeer)
	// GetPeers returns the NetworkMembers considered alive
	Peers() []discovery.NetworkMember

	// PeersOfChannel returns the NetworkMembers considered alive
	// and also subscribed to the channel given
	PeersOfChannel(common.ChainID) []discovery.NetworkMember
	// UpdateLedgerHeight updates the ledger height the peer
	// publishes to other peers in the channel
	UpdateLedgerHeight(height uint64, chainID common.ChainID)

	// Gossip sends a message to other peers to the network
	Gossip(msg *proto.GossipMessage)
	
	// Accept returns a dedicated read-only channel for messages sent by other nodes that match a certain predicate.
	// If passThrough is false, the messages are processed by the gossip layer beforehand.
	// If passThrough is true, the gossip layer doesn't intervene and the messages
	// can be used to send a reply back to the sender
	Accept(acceptor common.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan proto.ReceivedMessage)

	// JoinChan makes the Gossip instance join a channel
	JoinChan(joinMsg api.JoinChannelMessage, chainID common.ChainID)

	// LeaveChan makes the Gossip instance leave a channel.
	// It still disseminates stateInfo message, but doesn't participate
	// in block pulling anymore, and can't return anymore a list of peers
	// in the channel.
	LeaveChan(chainID common.ChainID)
	
	// Stop stops the gossip component
	Stop()
}

主要模塊

初始化和服務啟動

消息廣播

PeerA通過gossip協議廣播消息,PeerB為其中一個消息接收節點。

代碼應用框架

//初始化並加入通道‘A’
gossip = NewGossipInstance(15000, 1, 1000, isBoot)
gossip.JoinChan(&JoinChanMsg{}, common.ChainID("A"))
gossip.UpdateLedgerHeight(1, common.ChainID("A"))
acceptChan, _ := gossip.Accept(AcceptData, false) //AcceptData未消息選擇器
	
//通過gossip的方式來發送消息
gossip.Gossip(msg *pb.GossipMessage)

注:gossip發送消息后,對端節點接收到消息,會把過濾的消息坊到accetpChan通道中。

gossip pull機制

消息類型

pull機制主要涉及四種消息類型
GossipHello - hello消息
DataDigest - 消息摘要
DataRequest - 摘要請求
DataUpdate - 摘要應答
具體pull的內容包括: 未定義消息,塊消息,身份消息

初始化

pull機制的四個步驟

關鍵參數和函數

PullPeerNum //從PullPeerNum個節點pull數據
PullInterval //pull引擎每隔PullInterval開始一次pull同步

createBlockPuller: //創建pull.Mediator
- IngressDigFilter(大於本地高度的區塊)//用來過濾digest,返回自己要同步數據的摘要
- IdExtractor: seqNumFromMsg //要同步數據的唯一標識
                    

注: IDExtractor是個接口,區塊數據用塊高標識;身份數據用證書或者公鑰相關數據表示


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM