Hyperledger Fabric — Ordering Service

本文是對排序服務(Ordering service)的概念性介紹,Orderer如何與對等(pper)交互,Ordering service在交易流程(transaction flow)中扮演的角色,以及排序服務的現行可執行的作業概述,本文將會舉例 以Raft 來做為排序服務的實現。

哪甚麼是Ordering 呢?

許多區塊鏈,例如以太坊和比特幣,是非許可制的,這意味著任何節點與任何人都可以參與形成共識過程,其中交易被排序並捆綁到區塊中。基於這個事實,這些系統依賴於概率共識演算法(probabilistic consensus algorithms),最終保證分佈式帳本一致性的概率很高,但仍然容易受到不同帳本(也稱為帳本“分叉-fork”)的影響,整個區塊鍊中的不同參與者有接受交易順序的不同觀點(但這也是一開始區塊鏈的核心概念 — 民主於去中心化)。

Hyperledger Fabric 的作業方式不同,它是給企業用的(企業中是不能講民主的,不然就亂了套)。它具有一個稱為排序節點(也稱為“排序節點”)的節點,用於執行此交易排序,它與其他Ordering nodes一起形成Ordering service。因為 Fabric 的設計依賴於確定性(deterministic)的共識演算法,所以任何由對等(peer)驗證的區塊都可以保證是最終的和正確的。Fabric帳本不能像在許多其他非許可的區塊鏈網路中那樣分叉。另外Fabric的節點運作(在公有鏈稱為礦工)也不依靠維護帳本的手續費來運作,一切都是參與的企業要自行維護這些節點(基礎設施)。

除了促進最終確定性之外,將chaincode執行(發生在peers)的背書(endorsement)與排序(ordering)分開,使 Fabric 在效能和可擴展性方面具有優勢,消除了在同一節點執行執行和排序時可能出現的效能/擴充性瓶頸。

排序節點與渠道配置

排序者(Orderers)還對渠道實施基本的access control,限制誰可以讀取和寫入資料,以及誰可以配置它們。 但我們需要記得的是,誰有權修改渠道中的配置參數取決於相關管理員在建立社群或渠道時設置的政策。 配置交易(Configuration transactions)由 排序者處理,因為它需要知道現行的一組政策來執行其基本形式的access control。 在這種情況下,排序者處理配置更新以確保交易請求者俱有適當的管理權限。 如果是這樣,排序者會根據現有渠置驗證更新請求,產生新的配置交易,並將其打包到一個區塊中,該區塊散發到渠道上的所有對等點(peers)。 然後對等點處理配置交易,以驗證排序者批准的修改確實滿足渠道中定義的政策。

排序者節點與身分(Identity)

與區塊鏈網路交互的所有事物,包括對等點、應用程式、管理員和排序者,都從是從他們的憑證和MSP的參數中得到他們的組織身份。

就像對等點一樣,排序節點屬於一個組織。 與對等點(peers)類似,每個組織都應使用單獨的CA。 此 CA 是否將用作Root CA,或者我們是否選擇部署Root CA,然後再部署與該Root CA 關聯的Intermediate CA,這取決於我們的需求。

排序者與交易流程

第一階段: 交易提案(Transaction proposal)與背書(Endorsement)

我們在 對等點(Peers) 的文章中提到,對等點構成了區塊鏈網路的基礎,託管帳本,應用程式可以透過chaincode查詢和更新帳本。

具體來說,想要更新帳本的應用程式涉及一個具有三個階段的過程,以確保區塊鏈網絡中的所有對等點保持這本帳本是一致的。

在第一階段,Client Application通過受信任的對等點向 Fabric Gateway service發送transaction proposal。該對等點執行提議的交易或將其轉發到同一個組織中的另一個對等點來執行。

Fabric Gateway service還將交易轉發給背書政策所需要的組織中的對等點,也就是負責背書的節點。這些背書節點運行交易並將交易的回應返回給Fabric Gateway service。他們這個階段不會將提議的更新寫進於他們的帳本副本。背書後的交易提案最終將在第二階段被排序成區塊,然後在第三階段分發給所有對等節點進行最終驗證和寫入到帳本。

第二階段:交易的提交與排序

成功完成第一個交易階段(交易提案)後,Client application已收到來自 Fabric Gateway service的一個有背書的交易提案(來源自對等點)。對於背書交易,Fabric Gateway service將交易轉發給排序服務(Ordering service),排序服務會跟其他背書交易一起排序,然後將它們全部打包到一個區塊中。

排序服務建立這些交易區塊,最終將分發給渠道上的所有對等點,才可以在第三階段對帳本進行驗證和寫入。區塊本身也是有排序的,是區塊鏈帳本的基本組成部分。

排序服務節點同時從許多不同的Application client(通過Fabric Gateway service)接收交易。這些排序服務節點共同構成排序服務,可以被多個渠道共享。

區塊中的交易數量取決於與區塊的大小和最大經過持續時間(也就是要等多久才將積累交易打包)相關的渠道配置參數(確切地說是 BatchSize 和 BatchTimeout 參數)。然後將區塊保存到排序者的帳本並分發給渠道上的所有對等點。如果此時一個節點恰好掛掉,或者稍後才加入渠道,它將通過與另一個節點溝通來接收區塊。我們將在第三階段看到對等點如何處理這種區塊。

我們要注意的是,一個區塊中交易的順序不一定與排序服務接收的順序相同,因為可能有多個排序服務節點幾乎同時接收交易。重要的是排序服務將交易置於嚴格的順序中,節點在驗證和寫入交易時使用的是這個順序。

這種區塊內交易的嚴格排序使得 Hyperledger Fabric 與其他區塊鏈略有不同,後者將相同的交易打包到多個不同的區塊中競爭形成一條鏈(也就是最長鏈原則)。在 Hyperledger Fabric 中,排序服務產生的區塊是最終的,不需要競爭誰是最長鏈。一旦交易被寫入一個區塊,它在帳本中的位置就永遠不會改變。正如我們之前所說,Hyperledger Fabric 的最終性意味著沒有帳本分叉 — — 經過驗證和寫入的交易永遠不會被還原或丟棄。

我們還可以看到,雖然 對等點執行chaincode並處理交易,但排序者絕對不做這件事。每個到達 排序者的授權交易都會機械式打包到一個區塊中 — — 排序者不會對交易的內容做出判斷(渠道配置交易除外)。

在第二階段結束時,我們看到排序者負責收集提議的交易更新、排序並將它們打包區塊,準備分發給通道中的對等點的重要的過程。

第三階段:交易的驗證(validation)與寫入(commitment)

交易工作流程的第三階段涉及將已排序和已打包的區塊從排序服務散發到渠道中的對等點,以驗證和寫入到帳本。

第三階段從排序服務向所有渠道中的對等點散發區塊開始。需要注意的是,並非每個對等點都需要連接到排序節點 — — 對等點可以使用gossip協議將區塊逐步發散到其他對等點(儘管直接從排序服務接收區塊會是比較好的做法)。

每個對等點將獨立驗證收到的區塊,確保帳本保持一致。具體來說,渠道中的每個對等方將驗證區塊中的每筆交易,以確保它已被所需要的組織背書過了,其背書匹配,並且它沒有被其他最近提交的交易變為無效。無效交易仍保留在排序者建立的不可變區塊中,但它們被對等方標記為無效,並且不會更新帳本的狀態。

排序節點的第二個作用是將區塊分發給對等節點。 在上面範例中,排序者 O1 將區塊 B2 分發給對等點 P1 和對等點 P2。 對等點 P1 處理區塊 B2,從而將一個新區塊加到 P1 上的帳本 L1。 同時,對等點 P2 處理區塊 B2,從而將一個新區塊加到 P2 上的帳本 L1 中。 一旦這個過程完成,帳本 L1 就會在對等節點 P1 和 P2 上持續更新,並且每個節點都可以通知連接過來的應用程式這個交易已被處理。

總之,第三階段看到由排序服務建立的交易區塊被節點一致性的套用在帳本。 交易寫到區塊中的嚴格排序允許每個對等方驗證交易更新是否在渠道中一致性的套用。

排序服務的施作

儘管當前可用的每個排序服務都以相同的方式處理交易和配置更新,但仍有幾種不同的方法可以在排序服務節點之間對交易的嚴格排序達成共識。更多的關於建立排序節點的資訊,可參閱deploying a production ordering service文章

  • Raft(建議使用的) — 從 v1.4.1 開始,Raft 是一個基於 etcd 中 Raft 協議實現的CFT(crash fault tolerant) 排序服務。 Raft 遵循“leader and follower”模型,其中選出leader node(每個渠道都要有一個),其決策由follower複製。 Raft 排序服務應該比基於 Kafka 的排序服務更容易設置和管理,並且它們的設計允許不同的組織為提供有排序服務的節點。
  • Kafka與Solo均在 v2.x版本後廢除,故本文不再敘述。有興趣的讀者可以拜一下Google大神。

Raft介紹

正式Fabric網路的排序服務選擇,已建立的 Raft 協議的 Fabric 實現使用“領leader and follower”模型,其中leader在渠道中的排序節點之間動態選出來(這個節點集合稱為“consenter set”),並且該leader將訊息複製到follower節點。因為系統可以承受節點掛掉,包括leader節點(再選一個出來就可以),只要剩餘大多數排序節點(所謂的“仲裁[quorum]”),Raft 就被稱為“崩潰容錯”(CFT)。換句話說,如果一個渠道中有三個節點,它可以承受一個節點掛掉(剩下兩個)。如果一個渠道中有五個節點,則可能會承受掛掉兩個(剩下三個節點)。 Raft 排序服務的這一特性是為我們的排序服務建立高可用性的一個因素。此外,在正式環境中,我們可能希望將這些節點分散在不同的資料中心。

從它們提供給網路或渠道的服務的角度來看,Raft 和現有的基於 Kafka 的排序服務是相似的。它們都是使用leader和follower設計的 CFT 排序服務。如果我們是應用程式開發人員、chaincode開發人員或對等管理員,我們可能不會注意到基於 Raft 的排序服務與 Kafka 之間的功能差異。但是,有一些主要差異要考慮,特別是如果我們是管排序服務的。其主要差異如下:

  • Raft 更容易設定。儘管 Kafka 也有很多愛用者,但即使是那些愛用者(通常)也會承認,部署 Kafka cluster及其 ZooKeeper ensemble可能很麻煩,需要在 Kafka 基礎設施和設置方面是專家。此外,與 Raft 相比,使用 Kafka 管理的組件要多得多,這意味著出現問題的地方可能更多。 Kafka 也有自己的版本,我們必須與排序者搭配(可能升級時版本不匹配)。使用 Raft,一切都內嵌到我們的排序節點中。
  • Kafka 和 Zookeeper 並非適合跨大型網路來運作。雖然 Kafka 是 CFT,但它應該在一組cluster的主機是離很近(同一個資料中心或機櫃)運作。這意味著實際上我們只能一個組織運作 Kafka cluster。有鑑於此,在使用 Kafka(Fabric 舊版本有支援)時讓不同的組織運行排序節點並不會分散節點,因為最終節點都會進入一個受單一個組織控制的 Kafka cluster。使用 Raft,每個組織都可以擁有自己的排序節點,參與排序服務,從而形成一個更加去中心化的系統。
  • Kafka 是Fabric原生支援的,這意味著企業需要再花人力時間學習如何使用 Kafka 和 ZooKeeper。同樣,對 Kafka 相關問題的支援是通過 Apache 處理的,Apache 是 Kafka 的開源開發者,而不是 Hyperledger Fabric。另一方面,Fabric Raft 實現已經開發出來,並將在 Fabric 開發者社區及其支持設備中得到支援。
  • Kafka 使用servers pool(稱為“Kafka brokers”),排序組織的管理員指定他們希望在特定渠道上使用多少個節點,Raft 允許企業指定將哪些排序節點部署到哪個渠道。用這種方式,參與的對等組織可以確保的是,如果他們還擁有一個 排序者,則該節點將成為該渠道的排序服務的一部分,而不是信任並依賴中央管理員來管理 Kafka 節點。
  • Raft 是 Fabric 開發拜占庭容錯 (byzantine fault tolerant) 排序服務的第一步。正如我們將看到的,Raft 開發中的一些決定是受此驅動的。

另外 Solo 和 Kafka 類似,Raft 排序服務可能會在收到確認已發送給client後遺失交易。 例如,如果leader在大約與follower提供接收確認的同時掛掉。 因此,Application client無論如何都應該監聽對等方的交易提交事件(以檢查交易的有效性),但應格外小心以確保cleint也能從容地容忍交易未在配置的時間範圍內提交的超時。 根據應用程式,可能需要在此類超時時重新提交交易或收集一組新的背書。

Raft的概念

雖然 Raft 提供了許多與 Kafka 相同的功能 — — 儘管是在一個更簡單、更易於使用的軟體中 — — 但它在功能上與 Kafka 大不相同,並對Fabric 導入了許多新概念或對現有概念的扭曲。

Log entry — Raft 排序服務中的主要工作單元是“log entry”,這些entry的完整序列稱為“log(日誌)”。如果大多數成員(換句話說,法定人數-quorum)同意entry及其順序,我們就認為日誌是一致的,從而使各個排序者上的日誌被複製。

Consenter set — 排序節點會主動的參與給定渠道的共識機制並接收渠道的複制logs。

FSM (Finite-state Machine) — Raft 中的每個排序節點都有一個 FSM,它們共同用於確保各個排序節點中的日誌序列是確定性的(以相同的順序寫入)。

Quorum(法定人數) — 需要確認提案以便可以排序交易的最小同意者數量。對於每個Consenter set,這是大多數節點。例如在具有五個節點的cluster中,必須有三個節點同意才能達到法定人數。如果由於某種原因導致一定數量的節點掛掉(也可能是網路不通),則排序服務的cluster將無法在渠道上進行讀寫操作,並且無法提交新的日誌。

leader — Kafka 也使用leader — — 但重要的是要理解,在任何特定時間,渠道的Consenter set都會選出一個節點作為leader(我們將在後面描述這在 Raft 中是如何發生的)。Leader負責擷取新的log entries,將它們複製到Follower排序節點,並管理何時確認entries已提交。這不是特殊類型的排序者。這只是排序者在某些時候可能具有的角色,而不是其他時間,視情況而定。

Follower — 同樣的,這也不是一個新概念,但了解follower的關鍵是follower從leader那裡接收日誌並複制它們,確保日誌保持一致。正如我們將在關於選出leader的部分中看到的那樣,Follower也會收到來自leader的“heartbeat”訊息。如果leader在已經設定好的時間內停止發送這些訊息,則follower將發起新的leader選舉,其中一個將被選舉為新leader。

交易流程中的Raft

每個渠道都運行在 Raft 協議的一個單獨insatnce上,這允許每個insatnce選舉一個不同的leader。這種配置還允許在一個cluster上由不同組織控制的排序節點所組成的使用場景以進一步分散服務。可以根據需要在渠道中加入或刪除排序節點。雖然這種配置會以redundant heartbeat messages和 goroutine 的形式產生更多的overhead,但它為 拜占庭容錯 (byzantine fault tolerant)奠定了必要的基礎。

在 Raft 中,交易(以提案或配置更新的形式)由接收交易的排序節點自動路由到該渠道的當前的leader。這意味著對等節點和應用程式不需要在任何特定時間知道leader節點是誰。只有排序節點需要知道。

當排序者完成驗證檢查後,對交易進行排序、打包成區塊、同意並散發,如我們交易流程的第二階段所述。

整體架構事項

在Raft如何選出Leader

Raft 節點始終處於以下三種狀態之一:follower、candidate或leader。 所有節點最初都是作為follower開始的。 在這種狀態下,他們可以接受來自leader的log entry(如果已選出一個leader),或者為選出一個leader進行投票。 如果在設定的時間(例如,10秒)內沒有收到lon entry或heartbeats,節點會說自己是candidate狀態。 在candidate狀態下,節點向其他節點請求投票。 如果canaidate獲得法定人數的選票,則將其提升為leader。 leader必須接受新的log entry並將它們複製給follower。此連結用圖形化的方式逐步解釋整個選舉過程。

Snapshots

如果排序節點出現故障,它如何在重新啟動時獲取沒收到的日誌?

雖然可以無限期地保留所有日誌,但為了節省硬碟空間,Raft 使用了一個稱為“snapshot”的過程,我們可以在其中定義將在日誌中保留多少bytes的資料。 該資料量將符合一定數量的區塊(這取決於區塊中的數據量。要注意,snapshot中只存完整區塊)。

例如,假設滯後的副本 R1 剛剛重新連接到網路。 它的最後收到的區塊是 100。Leader L 位於區塊 196,並配置為每20個區塊做一次snapshot。 因此,R1 將從 L 接收區塊 180,然後對區塊 101 到 180 發出交付請求。完成後,區塊 180 到 196 將通過正常的 Raft 協議複製到 R1。

--

--

運用"雲端服務"加速企業的數位轉型願景
運用"雲端服務"加速企業的數位轉型願景

Written by 運用"雲端服務"加速企業的數位轉型願景

我們協助您駕馭名為"雲端運算"的怪獸,馴服它為您所用。諮詢請來信jason.kao@suros.com.tw. https://facebook.com/jason.kao.for.cloud

No responses yet