Hyperledger Fabric全面理解


Fabric 0.6與1.0+

Fabric結構

 

 

 

 
Fabric結構

Fabric 0.6的特點

  1. 結構簡單: 應用-成員管理-Peer的三角形關系,主要業務功能全部集中於Peer節點;
  2. 架構問題:由於peer節點承擔了太多的功能,所以帶來擴展性、可維護性、安全性、業務隔離等方面的諸多問題,所以0.6版本在推出后,並沒有大規模被行業使用,只是在一些零星的案例中進行業務驗證
 

 

 

 
Fabric 0.6

Fabric 1.0

 

 

 

 
Fabric 1.0
  1. 分拆Peer的功能,將Blockchain的數據維護和共識服務進行分離,共識服務從Peer節點中完全分離出來,獨立為Orderer節點提供共識服務;
  2. 基於新的架構,實現多通道(channel)的結構,實現了更為靈活的業務適應性(業務隔離、安全性等方面)
  3. 支持更強的配置功能和策略管理功能,進一步增強系統的靈活性和適應性;

Fabric結構理解

交易流程(數據傳輸流程)

在交代Fabric各個關鍵之前,先理清發起一筆交易需要經歷的整個數據流程是什么。

總體流程如下圖所示:

 

 

 

 
總體流程
生命周期中的流程
 

 

 

 
生命周期
完整生命周期
 

 

 

完整生命周期

流程步驟:

  1. 應用程序通過SDK發送請求到Peer節點(一個或多個) 即發起交易
    1. 客戶A發起交易請求:合約設置的背書策略規定所有交易需要經過兩個Peer節點的簽名背書,因此請求需要被同時發往Peer A和Peer B.
    2. 客戶端應用程序利用任意SDK(nodeJS,java,python)構造交易提案。該提案是一個調用智能合約功能函數的請求,用來確認哪些數據可以讀取或寫入賬本(即更新資產的Key/Value)。
    3. SDK將交易提案打包為可識別的格式(如gRPC上的protocol buffer),並使用用戶的加密憑證為該交易提案生成唯一的簽名。
  2. peer節點(Endorser節點)通過chaincode分別執行交易,但是並不將執行結果提交到本地的賬本中 (可以認為是模擬執行,交易處於掛起狀態,放置於候選池)
    1. 參與背書的peer將執行結果返回給應用程序(其中包括自身對背書結果的簽名)
    2. 背書節點(使用MSP)驗證簽名(ProcessPropsal()->preProcess()-->Verify()驗證簽名)並確定提交者是否有權執行操作(使用通道的ACL)。
    3. 背書節點將交易提案的參數作為輸入,在當前狀態數據庫上執行交易,生成包含執行返回值、讀操作集合和寫操作集合的交易結果(此時不會更新賬本),這些值的集合、背書節點的簽名和背書結果(YES / NO)作為“提案的結果”返回給SDK
    4. SDK解析這些信息判斷是否應用於后續的交易。
  3. 應用程序收集背書結果並將結果提交給Ordering服務節點
    1. 應用程序(SDK)驗證背書節點簽名,並比較各節點返回的提案結果,判斷提案結果是否一致以及是否參照指定的背書策略執行。
    2. 應用程序(SDK)將交易提案和結果以消息形式廣播到排序服務(Orderers/Consenter)。交易包含讀/寫操作集合、背書節點的簽名和通道ID。
    3. 排序服務不讀取交易的詳細信息,它從整個區塊鏈網絡接收交易信息,按通道分類進行排序,並為每個通道創建包含交易的區塊。
  4. Ordering服務節點執行共識過程並生成block,通過消息通道發布給Peer節點(所有節點包括committer, submitter, endorser),由peer節點各自驗證交易並提交到本地的ledger中(包括state狀態的變化)
    1. 排序服務將區塊發送到通道上的所有節點,所有交易需要被驗證,確保滿足背書策略
    2. 同時,需要確保全部讀操作集合在交易生成之后,賬本上的狀態值沒有改變。
    3. 經過驗證,區塊中的交易會被標記為有效或無效,通過Event通知客戶端
  5. 所有節點賬本更新
    1. 所有通道上的區塊鏈節點將新區塊加入區塊鏈,並且對於所有有效的交易,將寫操作集合提交更新到狀態數據庫中。
    2. 節點通過事件(Event)通知客戶端交易是否已被加入區塊鏈、以及交易是否有效。

Fabric概念結構

可以由下面的圖大致概括:
(Peers + Orderers + Channels)

 

 

 

 
概念結構
  • Orderers: 即Consenter,共識插件,提供共識服務的網絡節點,負責接受交易信息進行排序,以及對交易進行切割並打包,打包后返回批量交易。例如,使用Kafka或PBFT(SBFT),單節點使用solo單節點。
  • Peers: 維護賬本的網絡節點,通常在Hyperledger Fabric架構中存在各種角色,如endorser和committer。
  • 通道:通道是有共識服務(ordering)提供的一種通訊機制,類似於消息系統中的發布-訂閱(PUB/SUB)中的topic;基於這種發布-訂閱關系,將peer和orderer連接在一起,形成一個個具有保密性的通訊鏈路(虛擬),實現了業務隔離的要求;通道也與賬本(ledger)-狀態(worldstate)緊密相關; peer可以在訂閱多個通道,並且只能訪問訂閱通道上的交易;且通道上的數據僅與peer有關,與order無關。
  • 賬本:賬本保存Orders提交經節點確認的交易記錄。
  • 成員:訪問和使用賬本的網絡節點。
  • 成員管理: 每個membership(MSP組織)可以有自己的fabric-ca作為第三方認證機構,與背書策略對應。成員都需要在MSP中注冊
  • :基本上,一個鏈由1個通道+ 1個賬本+ N個成員組成。非鏈的成員無法訪問該鏈上的交易。鏈的成員可以由應用程序動態指定。

我們這時候再看一下前面的流程圖,回憶一下交易經過了哪些節點

SDK --> Commiters --> Endorsers --> SDK --> Orderers --> Commiters&Endorsers --> SDK

可參考下圖:

 

 

 

 
流程

在節點Peers(Committer)提交到Endorsers時,會根據交易的需求,要求一部分背書節點進行交易所有權驗證,背書簽名並返回背書結果。

下面我們了解一下背書策略

背書策略與設計

背書策略內容

背書策略,用於指示區塊鏈節點交易驗證的規則。作為交易驗證流程的一部分,當背書節點收到一個交易請求的時候, 該節點會調用 VSCC (驗證用途的系統合約程序) 並與執行交易的合約相關聯。

為了確定交易的有效性,一個交易應該包含來自盡可能多的背書節點的一個或多個背書。VSCC用於判定下面的內容:

  • 所有背書是有效的 (即它們是來自預期消息上的有效證書的有效簽名)
  • 得到一定數量的背書
  • 背書來自預期的來源(指定背書節點)

背書策略設計

背書策略有兩個主要組成部分:

  • 主體principal
  • 閥門threshold gate

P 標識期望背書的區塊鏈節點,T有兩個輸入參數:整數t(背書數量)和n (背書節點列表),即滿足t的條件,並得到n的背書
例如:

  1. T(2, 'A', 'B', 'C') 請求來自'A'、'B'、'C'的任意2個背書節點的簽名
  2. T(1, 'A', T(2, 'B', 'C')) 請求來自A或來自B和C中的一個簽名

命令行下的背書策略語法

在Fabric CLI中,使用了一種簡單的boolean表達式來解釋Endorse節點的背書策略。
Fabric 1.0使用MSP(成員管理服務)來描述主體principal,該MSP用於驗證簽名者的身份以及簽名者在該MSP內所具有的權限

目前支持兩種角色:成員和管理員。主體Principals的通用表現形式是MSP.ROLE,其中MSP是指MSP 的ID,ROLE是 member 或admin。 一個有效主體的示例是“Org0.admin”(Org0 MSP的任意管理員)或“Org1.member”(Org1 MSP的任意成員)。

示例:
命令行語法是這樣的:

EXPR(E[, E...])

其中EXPR可以是AND或OR,代表兩個boolean表達式,E是主體或對EXPR的另一個嵌套調用。
例如:

AND('Org1.member', 'Org2.member', 'Org3.member') 請求三個背書節點的簽名

OR('Org1.member', 'Org2.member') 請求兩個背書節點中的任意一個的簽名
 
OR('Org1.member', AND('Org2.member', 'Org3.member')) 
請求來自Org1 MSP成員或來自Org2 MSP成員和來自Org3 MSP成員的任意一個簽名
 

指定智能合約的背書策略

部署合約的開發人員可以指定背書策略來驗證執行的合約。

注,默認策略需要來自DEFAULT MSP成員的一個簽名。如果未在CLI中指定策略,則默認使用此選項。
背書策略可以在部署合約時使用"-P選項"指定,后面跟策略內容。
例如:

peer chaincode deploy -C testchainid -n mycc -p http://github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Args":["init","a","100","b","200"]}' -P "AND('Org1.member', 'Org2.member')"

執行這條命令將在testchainid這條鏈上使用背書策略AND('Org1.member', 'Org2.member').部署智能合約mycc

Orderers共識(Consenter)

共識機制

Fabric 0.6采用的是PBFT共識機制,但已經暫時取消該機制改為了Kafka共識。原因如下:

  • 交易性能達不到要求
  • Fabric 面向的聯盟鏈環境中,因為節點都是有准入控制的,拜贊庭容錯的需求不是很強烈,反而是並發性能最重要

在測試開發中較多使用SOLO共識機制

SOLO機制是一個非常容易部署的非生產環境的共識排序節點。由一個為所有客戶服務的單一節點組成,所以不需要“共識”,因為有一個中央權威機構。相應地沒有高可用性或可擴展性。這使得獨立開發和測試很理想,但不適合生產環境部署。order-solo模式作為單節點通信模式,所有從peer收到的消息都在本節點進行排序與生成數據塊

在Fabric 1.0往后版本中,采用的是Kafka共識機制,將來或采用SBFT(簡化拜占庭容錯共識)。

基於 Kafka 實現的共識

 
Kafka共識

一個共識集群由多個 orderer 節點(OSN)和一個 kafka 集群組成。orderer 之間並不直接通信,他們僅僅和 Kafka 集群通信。

在 orderer 的實現里,通道(Channel)在 kafka 中是以 主題topic 的形式隔離。
每個 orderer 內部,針對每個通道都會建立與 kafka 集群對應 topic 的生產者及消費者。生產者將 orderer 節點收到的交易發送到 kafka 集群進行排序,在生產的同時,消費者也同步消費排序后的交易。

如何鑒別某個交易屬於哪個區塊

Fabric 的區塊結塊由兩個條件決定,區塊交易量區塊時間間隔

  • 當配置的交易量達到閾值時,無論是否達到時間間隔,都會觸發結塊操作;
  • 另一方面,如果觸發了設置的時間間隔閾值,只要有交易就會觸發結塊操作,也就是說 fabric 中不會有空塊。
  • 結塊操作是由 orderer 節點中的 kafka 生產者發送一條 TTC-X(Time to cut block x)消息到 kafka 集群,
  • 當任意 orderer 節點的 kafka 消費者接收到任意節點發出的 TTC-X 消息時,都會將之前收到的交易打包結塊,保存在 orderer 本地,之后再分發到各 peer 節點。

個人理解:OSN內部有每個通道對應topic的kafka生產者、kafka消費者,OSN里的生產者同時發送交易到集群,OSN同時消費來自集群的交易,共識的交易達到交易量或達到時間間隔后,OSN的kafka生產者會發送TTC-X到集群,OSN的kafka消費者收到后會將之前收到的交易結塊,保存在OSN本地,然后分發到peers節點

以上過程可由下圖描述:

 

 

 

 
共識過程

Kafka共識集群結構

Kafka簡介

注,Orderers(OSN)與Consenter(一致性)不一樣,Consenter在kafka集群里,是真正實現共識的共識插件,而OSN是與集群cluster通信獲得共識結果的節點

Kafka是一種分布式的,基於發布/訂閱的消息系統。主要設計目標如下:

  • 以時間復雜度為O(1)的方式提供消息持久化能力,即使對TB級以上數據也能保證常數時間的訪問性能
  • 高吞吐率。即使在非常廉價的商用機器上也能做到單機支持每秒100K條消息的傳輸
  • 支持Kafka Server間的消息分區,及分布式消費,同時保證每個partition內的消息順序傳輸
  • 同時支持離線數據處理和實時數據處理
Kafka架構
 

 

 

 
Kafka架構

 

 

 

 
Kafka架構Partition

一個典型的kafka集群中包含若干producer,若干broker,若干consumer group,以及一個Zookeeper集群。

  • Kafka通過Zookeeper管理集群配置,選舉leader,以及在consumer group發生變化時進行rebalance
  • producer使用push模式將消息發布到broker
  • consumer使用pull模式從broker訂閱並消費消息。

各個角色的功能分別是:

  1. Brokers(經紀人)
    代理是負責維護發布數據的簡單系統。
    • 每個代理可以每個主題具有零個或多個分區。
    • push模式的目標是盡可能以最快速度傳遞消息,但是這樣很容易造成consumer來不及處理消息,而pull模式下Broker則可以根據consumer的消費能力以適當的速率消費消息。
    • 假設,如果在一個主題和N個代理中有N個分區,每個代理將有一個分區。
  2. Producers(生產者)
    生產者是發送給一個或多個Kafka主題的消息的發布者。
    • 生產者向Kafka經紀人發送數據。
    • 每當生產者將消息發布給代理時,代理只需將消息附加到最后一個段文件。實際上,該消息將被附加到分區。
    • 生產者還可以向他們選擇的分區發送消息。
  3. Consumers(消費者)
    Consumers從經紀人處讀取數據。 消費者訂閱一個或多個主題,並通過從代理中提取數據來使用已發布的消息。
    • Consumer自己維護消費到哪個offet,線性增加
    • 每個Consumer都有對應的group
    • group內是queue消費模型:各個Consumer消費不同的partition,因此一個消息在group內只消費一次
    • group間是publish-subscribe消費模型:各個group各自獨立消費,互不影響,因此一個消息被每個group消費一次
  4. Topics(主題)
    屬於特定類別的消息流稱為主題。
    • 數據存儲在主題中。Topic相當於Queue。
    • 主題被拆分成分區。
    • 每個這樣的分區包含不可變有序序列的消息。
    • 分區被實現為具有相等大小的一組分段文件。
  5. Partition(分區)
    一個Topic可以分成多個Partition,這是為了平行化處理。
    • 每個Partition內部消息有序,其中每個消息都有一個offset序號
    • 一個Partition只對應一個Broker,一個Broker可以管理多個Partition
    • 因為每條消息都被append到該partition中,是順序寫磁盤。因此效率非常高(經驗證,順序寫磁盤效率比隨機寫內存還要高,這是Kafka高吞吐率的一個很重要的保證)
  6. Replicas of partition(分區備份)
    • 副本只是一個分區的備份。 副本從不讀取或寫入數據。 它們用於防止數據丟失。
    • 對於傳統的message queue而言,一般會刪除已經被消費的消息,而Kafka集群會保留所有的消息,無論其被消費與否。
    • 當然,因為磁盤限制,不可能永久保留所有數據(實際上也沒必要),因此Kafka提供兩種策略去刪除舊數據。一是基於時間,二是基於partition文件大小。

Ledger賬本結構

 

 

 

賬本結構

Peer節點負責維護區塊鏈的賬本(ledger)和狀態(State),本地的賬本稱為PeerLedger。
整個區塊結構分為文件系統存儲的Block結構和數據庫維護的State狀態,其中state的存儲結構是可以替換的,可選的實現包括各種KV數據庫(LEVELDB,CouchDB等)

賬本簡單的說,是一系列有序的、不可篡改的狀態轉移記錄日志

  • 狀態轉移是鏈碼(chaincode)執行(交易)的結果,每個交易都是通過增刪改操作提交一系列鍵值對到賬本。一系列有序的交易被打包成塊,這樣就將賬本串聯成了區塊鏈。
  • 同時,一個狀態數據庫維護賬本當前的狀態,因此也被叫做世界狀態。

在 1.0 版本的 Fabric 中,每個通道都有其賬本,每個 peer 節點都保存着其加入的通道的賬本,包含着交易日志(賬本數據庫)、狀態數據庫以及歷史數據庫。

賬本狀態數據庫實際上存儲的是所有曾經在交易中出現的鍵值對的最新值

  • 調用鏈碼執行交易可以改變狀態數據,為了高效的執行鏈碼調用,所有數據的最新值都被存放在狀態數據庫中。
  • 就邏輯上來說,狀態數據庫僅僅是有序交易日志的快照,因此在任何時候都可以根據交易日志重新生成。
  • 狀態數據庫會在peer節點啟動的時候自動恢復或重構,未完備前,該節點不會接受新的交易。
  • 狀態數據庫可以使用 LevelDB 或者 CouchDB。
    • 跟 LevelDB 一樣,CouchDB 也能夠存儲任意的二進制數據,
    • CouchDB 額外的支撐 JSON 富文本查詢,如果鏈碼的鍵值對存儲的是 JSON,那么可以很好的利用 CouchDB 的富文本查詢功能。

Fabric 的賬本結構中還有一個可選的歷史狀態數據庫,用於查詢某個 key 的歷史修改記錄,需要注意的是,歷史數據庫並不存儲 key 具體的值,而只記錄在某個區塊的某個交易里,某 key 變動了一次。后續需要查詢的時候,根據變動歷史去查詢實際變動的值。

賬本數據庫是基於文件系統,將區塊存儲於文件塊中,然后在 LevelDB 中存儲區塊交易對應的文件塊及其偏移,也就是將 LevelDB 作為賬本數據庫的索引。
現階段支持的索引有:

  • 區塊編號
  • 區塊哈希
  • 交易 ID 索引交易
  • 區塊交易編號
  • 交易 ID 索引區塊
  • 交易 ID 索引交易驗證碼

Chaincode鏈碼系統

前面我們提到,狀態轉移是鏈碼(chaincode)執行(交易)的結果。實際上,鏈碼(chaincode)是 Hyperledger Fabric 提供的智能合約,是上層應用與底層區塊鏈平台交互的媒介。即,合約與交易都與鏈碼相關。

CSCC配置系統

介紹一個新的系統chaincode,叫做配置系統chaincode(CSCC),主要負責處理所有的配置相關的事務。CSCC提供方法查詢眾多的配置數據,包括通道配置。

鏈碼的通道配置

引導

共識服務由1個或多個Orderers組成。 每個Orderer配置有匹配的創世區塊,其由引導CLI命令生成,其提供了一些必要的數據,包括一系列可信根節點的列表,Order證書和IP地址的列表,一組特定的共識算法配置以及訪問控制策略(誰可以創建信道)。

要啟動並連接到共識服務,peer至少需要以下配置:

  1. 准入網絡的注冊證書。 證書可以來自任意CA,只要CA是peer將連接到的共識服務的可信任根的一部分
  2. 來自共識服務管理CLI生成的Orderer證書和IP地址的列表
  3. 可信任根節點列表
  4. peer可以訂閱的通道可選列表。 除非明確配置,否則peer在啟動時不訂閱任何通道

注意,#2和#3來自引導的創世區塊,我們可以從引導CLI命令獲得。
通過CLI或使用SDK API的應用程序,peer可以訂閱已經存在的通道。 orderer通過在通道創建或重新配置期間收到的消息決定誰可以加入通道。

例如,假設peer A和B屬於2個不同成員Alice和Bob。 請注意,Alice和Bob可能在網絡上有多個Peer,並且他們的任何Peer都可以加入通道。 以下是一個典型的序列:

創建通道
  1. 應用程序/ SDK獲得A和B的背書用於創建通道“foo”的配置交易。
  2. 應用程序/ SDK調用Broadcast RPC,將背書過的配置交易傳遞給order服務。
  3. 應用程序/ SDK然后調用在通道foo上deliver RPC。此RPC將返回一個錯誤,直到order服務成功創建通道。
  4. 當通道最終被創建后,Deliver RPC將返回通道的信息到應用程序/ SDK。在這一時點,通道foo應當僅具有包含相關訂閱者的創世區塊,並且與該配置交易一起被(或最近的重新配置交易)引導。
  5. 應用程序/ SDK在A和B上調用JoinChannel API,將通道foo的創世區塊傳遞給A和B,添加CSCC到通道上。
  6. A和B上的CSCC檢查創世區塊,包括檢查區塊中的配置交易的背書。如果一切正確,他們調用在通道上的Deliver RPC來開始接收塊。
    如果通道已經存在,則參與者列表將被替換。Orderers自動替換訂閱者並且將該交易與該通道上的其他交易一起發送給新成員,新成員將會同步完整的塊。
關閉通道

應用程序可以通過發送類似於創建通道的配置交易來關閉其創建的通道。 它需要根據應用程序設置的策略從通道參與方得到背書。

peer不會自動銷毀相關的賬本,但是裁剪進程會在適當的時候處理。
應用程序可以繼續從已關閉的賬本中讀取數據,只要該賬本尚未被刪除,但由於通道已被銷毀,因此不能執行交易了。

查詢通道

通道只能被該通道的成員查詢。也就是說,交易發起方的簽名能夠被存儲在賬本配置區塊中的CA證書驗證通過。這是通過發起一個查詢交易到CSCC,同時附上鏈的ID,返回的結果是一個配置區塊,里面包含了成員證書和一些其他的配置信息。

鏈上的交易

一個交易必須包含目標的鏈ID(鏈ID =通道ID =賬本ID)。
共識服務將把交易放置在由鏈ID標識的指定通道上,並且在該通道內被排序,而與其它通道上的交易無關。 最終在該通道上產生一個包含交易的區塊並發送到訂閱了該通道的那些peer。

注意,每個鏈都是獨立和並行的,因此一個peer可以同時接收和處理不同鏈上的區塊。
chaincode事務只能操作指定鏈中的狀態變量

chaincode限制
  1. 從交易調用chaincode總是在交易被發送的鏈上進行操作
  2. 只有系統鏈上的chaincode可以被私有鏈上的其他chaincode調用並且是只讀的
API 配置交易(通道與節點綁定)
  1. 在peer上增加一個新的gRPC API和一個新的頂層交易類型。API允許App / SDK通知peer已成功加入的通道。
    加入通道API的輸入是由新創建的通道上的共識服務返回的創世區塊,peer使用此區塊設置與通道關聯的賬本。
  2. 新的交易類型稱為配置交易,這種類型的交易可以由Orderer和peer處理。 創建或重新配置通道的交易都屬於配置交易,其中背書請求是讓peer批准和不批准它們創建或重新配置通道。 peer可以通過提案請求返回接受或拒絕。 為了保持靈活性,我們將提供一個系統chaincode來處理通道創建的背書請求,它將自動響應簽名請求。
  3. chaincode還提供查詢此通道上參與成員列表的功能。
  4. 新配置交易必須包含所有先前的配置條目,並且所有新/修改的配置條目必須用其包含配置包絡的序列號和鏈ID標記。每個配置條目都具有枚舉類型,唯一(按類型划分)ID以及由名稱引用的修改策略。Order服務將根據現有配置策略驗證配置交易,如果不滿足全部修改策略,則拒絕它。
  5. SDK可以向API提供進一步的抽象。 例如,它可以提供1個API,創建通道(成員證書列表),它將執行在創建通道部分中討論的所有6個步驟。
  6. 最后,SDK將調用應用程序上的回調,返回創建通道的狀態。

鏈碼的合約作用

鏈碼(chaincode)是 Hyperledger Fabric 提供的智能合約,是上層應用與底層區塊鏈平台交互的媒介。現階段,Fabric 提供 Go、Java 等語言編寫的鏈碼

所有的鏈碼都實現兩個接口,init 和 invoke。

  • init 接口用於初始化合約,在整個鏈碼的生命周期里,該接口僅僅執行一次。
  • invoke 接口是編寫業務邏輯的唯一入口,雖然只有一個入口,但是可以根據參數傳遞的不同自由區分不同業務邏輯,靈活性很高。比如應用開發者規定 Invoke 接口的第一個參數是合約方法名,剩余的 Invoke 參數列表是傳遞給該方法的參數,那么就可以在 Invoke 接口方法體中根據方法名的不同分流不同業務了。
合約里能夠獲取的內容
  • 輸入參數獲取。這點很好理解,我們只有知道此次調用的輸入,才能處理邏輯,推導輸出;
  • 與狀態數據庫和歷史數據庫交互。在合約層,我們可以將區塊鏈底層當做是一個鍵值對數據庫,合約就是對數據庫中鍵值的增刪改查;
  • 與其他合約的交互。在合約執行的過程中,可以與其他合約交換數據,做到類似跨鏈的效果。有了這種形式的數據獲取方式,其實就可以將聯系不緊密的業務邏輯拆分為多個合約,只在必要的時候跨合約調用,非常類似於現在提倡的微服務架構。

編寫鏈碼還有一個非常重要的原則:不要出現任何本地化和隨機邏輯。此處的本地化,不是指語言本地化,而是執行環境本地化。區塊鏈因為是去中心架構,業務邏輯不是只在某一個節點執行,而是在所有的共識節點都執行,如果鏈碼輸出與本地化數據相關,那么可能會導致結果差異,從而不能達成共識。

鏈碼部署

Peers是獨立實體,通道就是業務載體,鏈碼就是業務;不同的通道即便是運行相同的鏈碼,因為載體不同,可認為是兩個不同業務。

  1. 創建業務載體通道;
  2. 將通道與 peer 節點綁定;
  3. 在通道上實例化鏈碼。
通道的管理

通道只有創建,而沒有刪除功能。但是在使用 kafka 共識的過程中,如果數據操作不當,直接在 kafka 中刪除數據,而 orderer 沒有邏輯去處理這種異常刪除,因此會不斷的重試,在達到重試極限后直接崩潰整個進程

沒有完善的數據管理方案

在我們的使用場景中,數據增長是很快的,如果使用 CouchDB 作為底層數據引擎,數據更是幾何倍數的爆發。現有的解決方案只能是在雲上部署節點,提供可持續擴充的雲硬盤,再者使用 LevelDB 替換掉 CouchDB,避免使用模糊查詢。

Event事件流

事件框架支持發出2種類型的event(事件)

  • Block event
  • 自定義/chaincode event(在events.proto中定義的ChaincodeEvent類型)
基本思想

client(event consumers\事件消費者)將注冊event類型(block或chaincode)。在chaincode的情況下,它們可以指定附加的注冊標准,即chaincodeID和eventname。

  • ChaincodeID標識client想要查看event的特定Chaincode。
  • eventname是Chaincode開發人員,在調用Chaincode中的SetEvent API時嵌入的字符串。

調用transaction是當前唯一可以發出event的操作,並且每個調用,在每個transaction中只能發出一個event。

一般Event類型與ChaincodeEvent的關系

Event與event類型相關聯。 客戶注冊他們想要接收event的event類型。
event類型的生命周期由“block”event來說明

  1. 在啟動peer時,在支持的event類型中添加“block”
  2. client可以與peer(或多個peers)一起注冊感興趣的“block” event類型
  3. 創建Block的Peers,向所有注冊client發布event
  4. 客戶收到“block” event並處理Block中的事務

Chaincode event添加了額外的注冊過濾級別。 Chaincode event不是注冊給定event類型的所有event,而是允許client從特定Chaincode注冊特定event。 對於目前的第一個版本,為了簡單起見,沒有在eventname上實現通配符或正則表達式匹配,但后續會提供該功能

Fabric通信方式

節點通信、client與節點Api通信:使用http/2下的gRPC

  • http: 基於TCP/IP協議,需要三次握手
  • rpc:遠程進程調用,需要統一的序列化,不適用於頻繁連接
  • gRPC: 使用HTTP/2協議並用ProtoBuf作為序列化工具
與REST比較
  • 和REST一樣遵循HTTP協議(明確的說是HTTP/2),但是gRPC提供了全雙工流
  • 和傳統的REST不同的是gRPC使用了靜態路徑,從而提高性能
  • 用一些格式化的錯誤碼代替了HTTP的狀態碼更好的標示錯誤
gRPC
  1. xxx.proto, 定義rpc,輸入參數與返回參數的數據命名結構
  2. 命令行中protoc編譯生成對應的xxx.pb.go源碼,編寫clientAPI for EventService供客戶端使用的接口定義、接口實例、接口實例的初始化函數,和server API for EventService供服務端使用的接口定義,注冊函數。
HTTP/2特點
  1. 將所有傳輸的信息分割為更小的消息和幀,並對它們采用二進制格式的編碼。在HTTP/2中,數據流以消息的形式發送,而消息由一個或多個幀組成,幀可以在數據流上亂序發送,然后再根據每個幀首部的流標識符重新組裝。二進制分幀是HTTP/2的基石,其他優化都是在這一基礎上來實現的。我們先了解幾個概念:

    • 幀(Frame):HTTP/2通信的最小單位,每個幀包含幀首部,至少也會標識出當前幀所屬的流。
    • 消息(Message):由一個或多個幀組合而成,例如請求和響應。
    • 連接(Connection):與 HTTP/1 相同,都是指對應的 TCP 連接;
    • 流(Stream):已建立的連接上的雙向字節流。
  2. 支持請求與響應的多路復用來減少延遲

    • 同域名下所有通信都在單個連接上完成。
    • 單個連接可以承載任意數量的雙向數據流。
    • 數據流以消息的形式發送,而消息又由一個或多個幀組成,多個幀之間可以亂序發送,因為根據幀首部的流標識可以重新組裝。

    這一特性,性能會有極大的提升,因為:

    • 同個域名只需要占用一個TCP連接,消除了因多個TCP連接而帶來的延時和內存消耗。
    • 單個連接上可以並行交錯的請求和響應,之間互不干擾。
  3. 壓縮HTTP首部字段將協議開銷降至最低

    • HTTP/2在客戶端和服務器端使用“首部表”來跟蹤和存儲之前發送的鍵-值對,對於相同的數據,不再通過每次請求和響應發送;
    • 首部表在HTTP/2的連接存續期內始終存在,由客戶端和服務器共同漸進地更新;
    • 每個新的首部鍵-值對要么被追加到當前表的末尾,要么替換表中之前的值。
  4. 對請求划分優先級

  5. 支持服務端Push消息到客戶端

ProtoBuf:

  1. 一套用於數據存儲,網絡通信時用於協議編解碼的工具庫.它和XML和Json數據差不多,把數據已某種形式保存起來.Protobuf相對與XML和Json的不同之處,它是一種二進制的數據格式,具有更高的傳輸,打包和解包效率.
  2. 如果使用protobuf實現,首先要寫一個proto文件(不妨叫Order.proto),在該文件中添加一個名為"Order"的message結構,用來描述通訊協議中的結構化數據。使用protobuf內置的編譯器編譯 該proto。

參考資料:

Hyperledger文檔:(詳細研讀)
https://hyperledger-fabric.readthedocs.io/en/latest/whatis.html

Hyperledger github文檔
https://github.com/hyperledger/fabric/tree/release-1.1/docs/source

常用的Q&A
https://hyperledger-fabric.readthedocs.io/en/latest/Fabric-FAQ.html?highlight=consenter

知乎專欄翻譯:
https://zhuanlan.zhihu.com/p/23356616

專欄-fabric生命周期
https://zhuanlan.zhihu.com/p/25119939

hyperledger-MSP event等側面分析 圖解
https://blog.csdn.net/maixia24/article/category/7507736

 
 
16人點贊
 
 


https://www.jianshu.com/p/1d472586a3d5?from=timeline&isappinstalled=0


免責聲明!

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



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