圖片不能顯示時,請查看原文:https://lessisbetter.site/2019/12/17/fabric-blocks-from-orderer-to-peer/
Peer與Orderer的交互主要是組織的Peer主節點從Orderer獲取區塊,本文就來介紹,Peer是如何從Orderer獲取區塊的,順帶介紹爲何Peer從Orderer獲取的區塊“好慢”。
網絡拓撲
假設存在如下的Fabric網絡拓撲情況,本文使用此拓撲進行介紹Orderer到Peer的區塊傳播情況:
網絡中存在兩家組織:Org1和Org2,它們分別擁有Peer1作爲主節點,連向了排序服務的Orderer1節點。
網絡中存在2個應用channel:channel1和channel2,它們的賬本分別是channel1 ledger和channel2 ledger,Org1和Org2都加入了這2個channel。
channel間是隔離的,所以Peer和Orderer對不同的channel都會分別處理。
宏觀視角
下圖展示了Orderer向Peer傳遞區塊的宏觀視角,能夠展示多個通道在Orderer和Peer間傳遞區塊的情況:
- Orderer上有2個通道的賬本,每個Peer分別有2個Deliver Server對應2個通道的賬本,從賬本讀取區塊,發送給Peer。
- 每個Peer有2個Deliver Client,也對應2個通道,接收Orderer發來的區塊,加入到緩衝區Payloads Buffer,然後再從Payloads Buffer中提取區塊,驗證後寫入對應的通道賬本。
後面,介紹區塊同步某個通道區塊的情況。
單通道區塊同步
Peer利用Deliver從Orderer獲取區塊,就像SDK利用Deliver從Peer獲取區塊一樣,Deliver服務端的處理是一樣的,Deliver客戶端的處理就由SDK、Peer自行處理了。
Deliver本質是一個事件訂閱接口,Leading Peer啓動後,會爲每個通道,分別向Orderer節點註冊區塊事件,並且指定結束的區塊高度爲uint
類型的最大值,這是爲了不停的從orderer獲取區塊。
通過建立的gRPC連接,Orderer源源不斷的向Peer發送區塊,具體流程,如下圖所示:
- Orderer調用
deliverBlock
函數,該函數是循環函數,獲取區塊直到指定高度。 - 每當有新區塊產生,
deliverBlock
能利用NextBlock
從通道賬本中讀到最新的區塊,如果沒有最新區塊,NextBlock
會阻塞。 deliverBlock
把獲取的區塊封裝成區塊事件,發送給Peer(寫入到gRPC緩衝區)。- Peer從gRPC讀到區塊事件,把區塊提取出來後,加入到Payloads Buffer,Payloads Buffer默認大小爲200(通過源碼和日誌發現,Payloads Buffer實際存儲202個區塊),如果Orderer想向Peer發送更多的區塊,必須等Payloads Buffer被消費,有空閒的位置纔可以。
deliverPayloads
爲循環函數,不斷消費Payloads Buffer中的區塊,執行區塊驗證,添加區塊剩餘元數據,最後寫入通道賬本。- 寫通道賬本包含區塊寫入區塊賬本,修改世界狀態數據庫,歷史索引等。
爲何Peer從Orderer獲取區塊慢?
在性能測試過程中,我們發現Orderer排序完成後,Peer還在不斷的從Orderer獲取區塊,而不是所有排序後的區塊都先發送給Peer,Peer緩存起來,慢慢去驗證?
上面提到Orderer向Peer發送的區塊,Peer收到後先存到Payloads Buffer中,Buffer有空閒位置的時候,Orderer發送的區塊才能寫入Buffer,deliverBlock 1次循環才能完成,纔可以發送下一個區塊。
但Payloads Buffer大小是有限的,當Buffer滿後,Orderer發送區塊的操作也會收到阻塞。
我們可以把Orderer和Peer間發送區塊可以抽象一下,它們就是生產者-消費者模型,它們中間是緩衝區,Orderer是生產者,向緩衝區寫數據,Peer是消費者,從緩衝區讀數據,緩衝區滿了會阻塞生產者寫數據。
所以Orderer向Peer發送數據的快慢,取決消費者的速度,即取決於deliverPayloads處理一個區塊的快慢。
deliverPayloads慢在把區塊寫入區塊賬本,也就是寫賬本,成了整個網絡的瓶頸。
爲何不讓Peer緩存所有未處理的區塊?
從我們測試的情況看,Orderer排序的速度遠快於Peer,Peer和Orderer的高度差可以達到10萬+,如果讓Peer來緩存這些區塊,然後再做處理是需要耗費大量的空間。
在生產者-消費者模型中,只需要要消費者時刻都有數據處理即可。雖然Orderer和Peer之間是網絡傳輸,測試網絡比較可靠,傳輸速度遠比Peer處理區塊要快。
Payloads Buffer可以讓網絡傳輸區塊和Peer處理區塊並行,這樣縮短了一個區塊從Orderer中發出,到Peer寫入區塊到賬本的總時間,提升Fabric網絡整體性能。