本文基於 Fabric v2.0.1
一、Gossip 簡介
參見 Gossip 協議
二、Gossip 在 Fabric 中的應用
Fabric 使用 Gossip 作爲 Peer 間的數據共享網絡。在其上劃分 Channel 進行消息交換,主要用於 Fabric 網絡成員發現、組織內區塊數據交換、私有數據的分發、及同步 Peer Channel 當前狀態等。
Peer 間建立連接時握手過程會交換彼此的證書、並使用對方的證書進行身份認證。
Gossip 中交換的消息類型見 message.proto
oneof content {
// Membership
AliveMessage alive_msg = 5;
MembershipRequest mem_req = 6;
MembershipResponse mem_res = 7;
// Contains a ledger block
DataMessage data_msg = 8;
// Used for push&pull
GossipHello hello = 9;
DataDigest data_dig = 10;
DataRequest data_req = 11;
DataUpdate data_update = 12;
// Empty message, used for pinging
Empty empty = 13;
// ConnEstablish, used for establishing a connection
ConnEstablish conn = 14;
// Used for relaying information
// about state
StateInfo state_info = 15;
// Used for sending sets of StateInfo messages
StateInfoSnapshot state_snapshot = 16;
// Used for asking for StateInfoSnapshots
StateInfoPullRequest state_info_pull_req = 17;
// Used to ask from a remote peer a set of blocks
RemoteStateRequest state_request = 18;
// Used to send a set of blocks to a remote peer
RemoteStateResponse state_response = 19;
// Used to indicate intent of peer to become leader
LeadershipMessage leadership_msg = 20;
// Used to learn of a peer's certificate
PeerIdentity peer_identity = 21;
Acknowledgement ack = 22;
// Used to request private data
RemotePvtDataRequest privateReq = 23;
// Used to respond to private data requests
RemotePvtDataResponse privateRes = 24;
// Encapsulates private data used to distribute
// private rwset after the endorsement
PrivateDataMessage private_data = 25;
}
2.1 Fabric Gossip Components
按包結構劃分 Fabric Gossip 分爲以下組件:
- gossip/comm :負責 Peer 節點間的 RPC 通信
- gossip/discovery :Fabric 網絡成員發現、管理
- gossip/election :組織內 Peer 節點選舉
- gossip/gossip :Gossip 協議實現
- gossip/identity :節點身份標識管理
- gossip/privdata :私有數據處理部分
- gossip/service :封裝 Gossip 功能對位不提供服務
- gossip/state :節點參與的 Channel 狀態管理、區塊數據、私有數據與本地賬本的對接
Fabric Gossip 組件圖如下:
圖片使用 plantuml 生成,腳本見1
2.2 從 Orderer 接收區塊數據
Fabric 中在同一組織內是由擔任 Leader
角色的 Gossip Node
負責從 Orderer 接收完成排序的區塊,分發給其他 Follower
。需要注意 Leader
是 Pre Channel 的每個 Channel 有自己的 Leader
。
Leader
有兩種方式產生,通過設置 core.yaml 相應配置如下 :
- 靜態指定(靜態方式下, 都設置爲 false 即爲
Follower
)peer: gossip: useLeaderElection: false orgLeader: true
- 動態選舉產生
peer: gossip: useLeaderElection: true orgLeader: false
Leader
從 Orderer 接收區塊過程如下圖所示:
圖片使用 plantuml 生成,腳本見1
在 InitializeChannel
階段初始化 deliveryService
當前節點成爲 Leader
時連接 Orderer 節點接收區塊數據。接收到新區塊時完成基本校驗後調用 GossipService
的 AddPayload
方法,在 GossipService
內部將區塊數據提交給本 Channel 的 State 並通過 Gossip
接口向 Follower
傳播。
2.3 區塊數據的傳播
Follower
有三個途徑接收區塊數據:
- Gossip / Forward 選中
在消息單線傳播時被隨機選中,初始的 Leader Gossip 或後續的 Follower Forward時被選中 - 通過
BlocksPuller
主動從其他節點獲取
BlocksPuller
會記錄一定時間內的 Gossip 網絡中的區塊消息並與其他節點交換當前擁有的區塊ID,需要時從其他節點獲取 - 通過
State
從其他節點同步
Chain State
在進行初始化時會根據配置項(peer.gossip.state.enabled
),決定是否啓動 Gossip 網絡的Anti Entropy
模式,啓用的情況下定時從其他節點同步區塊高度。
前兩種接收途徑如下圖藍色路徑所示:
圖片使用 plantuml 生成,腳本見1
2.4 私有數據的分發
Fabric 中私有數據不通過 Orderer 節點,在背書階段通過 Gossip 網絡進行分發。分發的策略由 Chaincode approve
時指定的 CollectionConfig 來決定。
部分流程如下圖所示:
圖片使用 plantuml 生成,腳本見1
圖中只表示了私有數據的分發過程,不包含主動獲取部分,在完成區塊的驗證之後,會在提交到賬本處理前會從 背書節點 獲取本地沒有的私有數據。另外如果啓用了 reconciler
(通過配置項 peer.gossip.pvtData.reconciliationEnabled
配置)會定時查詢 本地賬本 確實的私有數據從其他 CollectionConfig
允許的節點獲取私有數據放入 本地賬本 中。