如何使用 AWS Spot Instances 建置 ABT 鏈網路

作者: Tyr Chen(ArcBlock 工程副總裁)
編輯: Matt McKinney
3 月 29 日星期五,ABT Network 正式發布。ABT Network 利用雲端節點與互連鏈建立網路,以完全去中心化的方式連接彼此互通的區塊鏈網路,重新定義下一代區塊鏈基礎設施。本文回顧過去幾個月裡,我們從構想走向公開發布期間的一些有趣經歷,包括團隊一路上進行的實驗、遭遇的阻礙以及取得的成果。

為了幫助你充分理解本文,我們先介紹幾個基本概念:
- ABT Network: 使用 ArcBlock 技術建置的多個區塊鏈網路。
- ABT Chain Node: 由 Forge Framework 建立的 ArcBlock 區塊鏈「節點」。
- Forge Framework: 一套完整的開發框架,包含建置及執行 DApp 所需的一切。
任何人都能部署節點
在開發 Forge Framework 與 ABT Chain Node 時,我們相信它既可用於每天處理數百萬筆交易的大型應用程式,也可用於 DIY 專案或小型獨立開發專案。因此,在 ABT Network 上,ABT Node 可以很大、很小,也可以介於兩者之間。我們的目標是確保它能滿足大多數使用情境與需求,無論伺服器規模如何,都能提供優質的使用者體驗。
舉例來說,我們將單一節點的費用目標定為 15 美元。在 Digital Ocean 上,這相當於以下配置:

因此,在每月 15 美元的預算下,可選擇從 1GB / 1CPU / 25GB 磁碟到 2GB / 2CPU / 60GB 的託管方案。
在 1 月和 2 月期間,大多數開發測試都使用 5 美元的 Extreme Edition 主機,並在西部(SF)、東部(NY)、西歐(倫敦)和東南亞(新加坡)部署節點,組成 P2P 網路來開發 Forge。透過建立這個資源非常有限的環境,我們能提前暴露各種問題,藉此測試並確保軟體穩健且可用。
網路架設完成後,我們需要足夠的流量來模擬真實世界的使用情境。為此,我們也開發了一套模擬器,使用內部開發的描述語言來描述模擬的啟動方式:
pools:
account_migrate: 5
create_asset: 5
declare: 5
exchange: 5
transfer: 10
update_asset: 5
consume_asset: 5
poke: 5
meta:
tick: 500
simulations:
- name: exchange token and assets
interval: 2
num: 2
type: exchange
settings:
value: "1000..20000"
- name: transfer token and assets
interval: 5
num: 2
type: transfer
settings:
value: "1000..5000"
after:
- interval: 1
action: consume_asset只要變更變數,我們就能輕鬆調整測試中的不同要素,包括共識、吞吐量等等。我們也可以加入更多模擬來改變流量的多樣性,藉此建立不同情境。
模擬器啟動後,我們的開發網路連續三天崩潰,遇到的問題包括記憶體不足、開啟過多檔案、gen_server 逾時,以及 TCP 傳送/接收緩衝區已滿。
如果只是將節點換成容量更大的機器,這些問題發生的機率便會降至零。然而,我們的目標是主動讓問題在開發環境中發生,以便找出並妥善處理大部分問題。例如,我們發現所使用的共識引擎不穩定,時常崩潰;崩潰後也很容易寫入 state DB(狀態資料庫),導致節點徹底崩潰而無法復原。對此,我們的做法是,一旦共識引擎崩潰,就讓 Forge 自動崩潰,再使用我們開發的 forge starter 重新啟動 forge。重新啟動後,我們回到最近一個區塊的資料並重新套用。如果共識引擎能夠復原,舊的狀態就會繼續回退;否則便會持續崩潰並持續回溯。
在如此嚴苛的環境中,Forge 逐漸成長,節點網路則不斷死亡又重生。看過湯姆·克魯斯主演《明日邊界》的人,會發現這個概念與 Forge 非常相似——學習、失敗,再重新開始。即使資源極其有限,每次迭代後節點都能存活得更久。然而,即便歷經各種改善,好景仍不長久。當我們接近 150 萬筆 TX 時,網路再次崩潰:

這次崩潰讓節點完全損毀,甚至無法再透過 ssh 存取。此時,Digital Ocean 節點的監控顯示 CPU 為 0,我們很快就確認問題是磁碟已滿。25GB 的空間全數用盡。因此,我們建立快照並進入下一階段。
3 月初,我們放棄每月 5 美元的雲端機器,改用每月 15 美元的「大型」節點。在 Digital Ocean 帳戶中,我們同時執行數個網路並進行滾動升級。剛開始時,我們每週有一個里程碑;到了 3 月第二週,則每天都有新版本。更新網路上的節點後,100 萬筆 TX 的里程碑被下一個 500 萬筆 TX 的目標取代。

此後,我們很快突破 600 萬筆 TX,接著達到 700 萬筆 TX,直到最後實作了一些破壞性變更,才讓計數停止。
ArcBlock 的工程團隊正在進行許多業界領先的開發工作,我們讓區塊鏈節點能在每月僅 15 美元的小型雲端機器上穩定執行,便是其中一例。過去一年,我們曾使用其他供應商的公鏈節點,而其建議配置往往需要每月超過 1,000 美元的雲端伺服器。
如果應用程式開發者想部署自己的鏈,初期透過自己的節點為使用者提供服務(我們假設節點部署在全球四個區域,每個區域兩個節點),開發者每月的成本將高達數萬美元。任何小型開發公司、開發者或使用者都沒有足夠資金支撐專案。我們的目標是將這個數字降低 100 倍,確保開發者每月只需花費數百美元,就能建置區塊鏈專案。
上述範例展示了一種使用情境。那麼,需要在具有更大型雲端伺服器的正式環境中部署、達到企業級要求的 DApp 又如何呢?ArcBlock 的節點與環境同樣具備企業級能力,其設計能支援遠超目前最大型 DApp 使用規模的應用程式。ArcBlock 自己的 ABT Network 執行於 Amazon Web Services,我們也已與 AWS、Azure 和 IBM 等領先的雲端供應商合作,提供 ABT Node 映像,讓你能輕鬆啟動自己的環境。接下來,讓我們更深入了解如何架設自己的 ABT Network。
簡單,卻不單純的正式環境
由於 ABT Network 強調將鏈互連成網路,我們從三個以週期表元素命名的鏈開始:「Argon」、「Bromine」和「Titanium」(其中 Bromine 是執行最新 nightly build 版本的測試鏈)。有了這三條鏈,我們需要為它們準備安全且可信賴的正式環境。
我們的正式環境包含以下需求:
- 每條鏈都部署至亞太及歐洲的四個區域;
- Argon 和 Titanium 各包含 16 個節點;Bromine 使用 4 個節點;
- 所有節點只公開 p2p 連接埠;
- 節點的 GraphQL RPC 及其區塊瀏覽器可透過 ELB 從外部存取,而 gRPC 僅允許本機存取;
- 每個區域中每條鏈的 ELB 網域名稱,都由 route 53 依延遲進行負載平衡。
為了協助管理所有這些部署,我們使用 Ansible 和 Terraform 進行大量自動化。與我們所做的其他事情一樣,我們嘗試找出既能降低成本,又能同時提升環境正式運作品質的方法。
採用上述配置時,如果只使用價格較低的 c4.large / c5.large,每個節點使用 110G EBS,且每條鏈在每個區域都配置一個 ELB,那麼一個月的固定成本為 3,721 美元。
計算公式:0.11(c4.large 價格)x 36 x 24 x 31 + 36 x 110 x 0.12(EBS 價格)+ 25(ELB 價格)x 12
其中,EC2 成本是最大的一筆——每月接近 3,000 美元。
那麼,有沒有辦法確保正式環境維持我們的可用性標準,同時降低成本?在 AWS 上,答案其實很直接,只是有幾點小小的注意事項。
我們的答案是 Spot Instances。Spot Instances 的前提很簡單:使用者可以用大幅折扣的價格購買閒置的 Amazon EC2 容量。這些 EC2 執行個體與一般 EC2 執行個體相同,但隨時可能遭到中斷。
下圖顯示 us-east-2 和 ap-southeast-1 中 spot instance 的價格趨勢:


只要使用 Spot Instances,我們就能將費用降至每月 600 美元,亦即每月總成本 1,300 美元,相較於上述每月超過 3,000 美元的成本大幅降低。成本看起來很理想,但使用 spot instances 時,如果執行個體遭到終止會發生什麼事?如何儘快恢復服務?又該如何縮短開發週期,讓機器自動切換並上線?
為了克服這項限制,我們將根磁碟與資料磁碟分離。Forge 儲存的所有資料都放在資料磁碟中。Forge 的配置、節點私鑰、認證節點私鑰則放在根磁碟,並在初始化後以 AES 加密方式備份。S3 bucket 只允許寫入一次。之後,節點執行期間,每條鏈的每個區域都會定期備份一個健康節點的資料磁碟。因此,當認證節點被終止時,我們可以從最近的備份還原資料磁碟,再從 S3 取回認證節點的私鑰與配置。
我們認為這個構想相當簡單直觀,但要讓它順利運作,仍需要一些規劃。就 ABT Network 而言,我們已測試並驗證 spot instances,目前也正用它們來執行具備正式運作能力的環境。這個方法確實可行;對 dApp 開發者或區塊鏈領域的其他同業而言,以 spot instance 執行區塊鏈節點的方式可以作為參考設計。
為了確保 spot instances 能如上所述運作,我們將部署指令碼 forge-deploy 分成四個部分:
- 只需執行一次的指令碼:例如,為每個區域中的每個 VPC 建立 security group;
- 製作 Forge AMI 的指令碼:每次發布新版本時,都建立新的 AMI;
- 為新鏈建立所需資源的指令碼:建立 spot request、EBS、ELB、target group,設定 listener(以及 listener rules),並建立網域名稱與網域名稱解析政策;
- 管理現有鏈的指令碼:例如初始化鏈、重新啟動節點、升級節點、修復受損節點、新增節點等等。
3 月最後兩週,我們的工程師以原本零散的指令碼(Digital Ocean 機器使用的指令碼)為基礎,開發並測試 forge-deploy。我們每天的例行工作是:建立一條鏈,摧毀它;再建立另一條鏈,然後摧毀它,如此一再重複。在這兩週內,我們解決了大多數區塊鏈團隊可能需要整整一年才能解決的問題。部署高峰期共有六條鏈平行執行。我們總共建立並摧毀了三十多條鏈,包括只存在一天的 abtchain、origin、bigbang、test、abc……請注意,這裡所說的「鏈」是指由多個節點組成、跨區域的鏈,而非單一節點的鏈。
由於先前的經驗帶給我們充分信心,在 ABT Network 預定上線當天,我們於最終倒數不到 30 分鐘前摧毀了三條鏈,以便重新建立它們,讓整個社群見證第一個區塊如何誕生。雖然指令碼的執行速度比預期慢,但倒數結束 20 分鐘後,Argon、Bromine 和 Titanium 三條鏈全都正式上線。部署一條鏈只需要兩個命令:

其中,create_fleet 會在四個區域中執行以下工作:
- 取得目前 zone 的預設 VPC id
- 取得 VPC 的 subnet id
- 取得數個預先建立的 security group id
- 使用預設配置為 certifier node 申請 spot fleet
- 使用預設配置為 sentinel nodes 申請 spot fleet
- 等待所有申請的 instances 正常運作
- 建立 ELB
- 建立 target group,並將所有 instances 加入 target group
- 取得預先上傳的 certificate id
- 建立兩個 ELB listeners;port 80 直接以 301 重新導向 443,而 port 443 將流量轉送至 target group
- 建立 DNS domain record,並設定 latency based policy
四個區域全部完成後,為鏈的所有 instances 建立 ansible inventory,以便進行後續處理。

接著,在 init_forge_network 中會執行以下工作:
- 將資料磁碟掛載至對應的 instance,並將檔案系統格式化為 XFS
- 使用暫存配置檔案啟動 Forge,產生 node key 與 validator key
- 將產生的 key 備份至 S3
- 根據 inventory file 找到 certifier node,並將其 validator address 寫入 genesis configuration
- 啟動 forge
所有節點啟動後,稍待片刻,一條鏈便誕生了!
如想進一步了解 ABT Network,請造訪 https://www.abtnetwork.io。
本頁涉及
產品
-
ArcBlock Chain
active
為應用的身分、資產與約定而設計的 Layer 1。ArcBlock Chain 將這些常用操作納入協議,ABT 是公共網路的原生代幣。
術語
-
Decentralization
它不是一個整體屬性,而是對每一部分分別要問的問題:誰能改動它、誰能扣住它、事後誰能核實它。一個系統通常只在某些部分是去中心的,另一些部分不是。
-
區塊鏈
透過密碼學連接記錄,並按共同的驗證與共識規則確定交易歷史的分散式帳本。