鏈碼作為外部服務
Fabric v2.0支持鏈碼在Fabric環境外部署和執行。允許用戶管理與節點保持獨立的鏈碼運行。這種方案激勵了Fabric中的鏈碼雲部署,例如Kubernetes
。代替了在每一個節點上面構建與運行鏈碼。鏈碼可以作為一個服務運行,它的生命周期將可以在Fabric環境外進行管理。這種措施利用Fabirc v2.0的外部構建和運行功能。其功能具有允許操作者通過程序構建,運行,發現鏈碼對節點進行擴展。在讀取本文內容之前,應該對外部構建與擴展較為熟悉。
在外部構建功能可以使用之前,鏈碼包內容要求指定的編程語言的源代碼進行構建並作為鏈碼二進制文件運行。新的外部構建和運行功能允許用戶有選擇地定制化構建過程。將鏈碼作為外部服務運行。構建過程允許指定鏈碼運行服務的端點信息。因此包內容可以簡單地由外部鏈碼運行服務端點信息和用於安全通信的TLS歸檔組成。TLS是可選的,但是除了簡單的測試環境以外,強烈建議所有環境都使用TLS。
接下來的部分將描述如何將鏈碼配置為外部服務:
打包鏈碼
通過Fabric V2.0版本的chaincode lifecycle
,鏈碼可以被打包並以.tar.gz
格式進行安裝。下面的myccpackage.tgz
歸檔說明了要求的結構:
tar xvfz myccpackage.tgz
code.tar.gz
metadata.json
code.tar.gz
歸檔要求
code.tar.gz
歸檔必須包含鏈碼端點的連接信息。該信息將在/bin/release
步驟處打包進connection.json
(見下面)。在這里直接將connection.json
打包進code.tar.gz
,所以release
步驟可以直接從這里復制。
address -
可以被peer
節點訪問的鏈碼服務端點,必須指定以:
格式。dial_timeout -
等待連接完成的間隔時間,字符串類型並需要指定單位,如"10s","500ms","1m"
,默認為"3s"
.tls_required -
是否使用TLS
加密。如果為false
則不要求使用下面四個屬性client_auth_required -
如果為true
則需要是定客戶端權限認證的key_path
,cert_path
.默認為false
.key_path -
秘鑰文件的路徑cert_path -
證書文件的路徑root_cert_path -
根證書文件路徑。
例如:
{
"address": "your.chaincode.host.com:9999",
"dial_timeout": "10s",
"tls_required": true,
"client_auth_required": "true",
"key_path": "path/rooted/in/release/directory/key.pem",
"cert_path": "path/rooted/in/release/directory/cert.pem",
"root_cert_path": "path/rooted/in/release/directory/rootcert.pem"
}
TLS
文件可以放在code.tar.gz
歸檔的任何地方,因為.tar.gz
文件夾內的文件內容將會提供給外部鏈碼構建腳本。bin/release
腳本,將會將文件移動到合適的位置。
metadata.json
文件要求
當使用鏈碼作為外部服務時,需要在metadata.json
文件中設置type
字段,為了指定使用的是外部服務,例如:
{"path":"","type":"external","label":"mycc"}
配置節點對外部鏈碼進行處理
這個過程和外部構建與擴展介紹的內容是相似的。利用這些腳本來定義外部鏈碼信息。這些腳本位於peer
節點的文件系統並且可以訪問並處理peer
節點處的core.yaml
文件中chaincode
部分定義的externalBuilders
元素。
創建peer
節點上的外部構建器和運行器腳本
為了配置鏈碼作為外部服務,必須使用以下腳本文件:
detect -
檢測metadata.json
文件中type
是否設置為external
並接受鏈碼包。build -
構建鏈碼並將構建的歸檔放置在BUILD_OUTPUT_DIR
位置。腳本提取connection.json
文件中的鏈碼端點信息並將code.tar.gz
文件中的其他歸檔文件放置在指定位置。release -
拷貝被構建的歸檔(在connection.sjon
文件中)到指定位置。
注意到對於鏈碼作為外部服務,沒有要求外部構建器和運行器bin/run
腳本。
腳本文件要求存在peer
節點的文件夾內:
<peer的環境下完全正確的路徑>
└── bin
├── build
├── detect
└── release
使peer
節點的core.yaml
文件包括externalBuilder
最后,為了讓peer
節點能夠使用外部構建器和運行器腳本,需要修改位於peer
節點的core.yaml
文件中的chaincode
部分,使它包括externalBuilder
配置元素。
externalBuilders:
- name: myexternal
path: <peer的環境下完全正確的路徑> #就是上面的那個路徑
外部構建和運行的腳本文件模板
為了幫助理解在鏈碼作為外部服務時,每一個腳本需要包含哪些工作,這一部分包含bin/detect,bin/build,bin/release
腳本示例。
這些例子使用jq
命令對json
個數數據進行轉換,可以通過運行jq --version
檢查是否安裝該工具。否則,需要安裝jq
或者對腳本文件進行適當的修改。
/bin/detect
bin/detect
腳本的職責是決定是否使用buildpack
對鏈碼包進行構建和運行。對於鏈碼作為外部服務,腳本需要檢測metadata.json
文件中的type
是否被設置為external
。peer
節點通過兩個參數調用該腳本:
bin/detect CHAINCODE_SOURCE_DIR CHAINCODE_METADATA_DIR
一個典型的detect
腳本應該包含:
#!/bin/bash
set -euo pipefail
if [ "$#" -ne 2 ]; then
>&2 echo "Expected 2 directories got $#"
exit 2
fi
#檢測`type`是否被設置為`external`
if [ "$(jq -r .type "$2/metadata.json")" == "external" ]; then
exit 0
fi
exit 1
metadata.json
文件應該包含以下關鍵點:
{"path":"","type":"external","label":"mycc"}
/bin/build
bin/build
腳本的職責是構建,編譯,以及轉換鏈碼包內容到可以被release
和run
使用的歸檔中。對於鏈碼作為外部服務,該腳本拷貝connection.json
文件到BUILD_OUTPUT_DIR
.peer
節點通過三個參數調用該腳本:
bin/build CHAINCODE_SOURCE_DIR CHAINCODE_METADATA_DIR BUILD_OUTPUT_DIR
一個典型的build
腳本應該包含:
#!/bin/bash
set -euo pipefail
if [ "$#" -ne 3 ]; then
>&2 echo "Expected 3 directories got $#"
exit 1
fi
SOURCE=$1
OUTPUT=$3
#檢查connection.json文件是否存在
if [ ! -f "$SOURCE/connection.json" ] ; then
>&2 echo "$SOURCE/connection.json not found"
exit 1
fi
#如果需要的話在這里做更多驗證
#簡單拷貝端點信息到指定的輸出位置
cp $SOURCE/connection.json $OUTPUT/connection.json
exit 0
/bin/release
bin/release
腳本的職責是為peer
節點提供鏈碼元數據。對於鏈碼作為外部服務,bin/release
腳本作用是為peer
提供放置在RELEASE_OUTPUT_DIR
位置的connection.json
文件。peer
節點通過兩個參數調用該腳本:
bin/release BUILD_OUTPUT_DIR RELEASE_OUTPUT_DIR
一個典型的release
腳本應該包含:
#!/bin/bash
set -euo pipefail
set -x
if [ "$#" -ne 2 ]; then
>&2 echo "Expected 2 directories got $#"
exit 2
fi
BLD="$1"
RELEASE="$2"
#外部鏈碼期望歸檔被放置在"$RELEASE"/chaincode/server路徑下
if [ -f $BLD/connection.json ]; then
mkdir -p "$RELEASE"/chaincode/server
cp $BLD/connection.json "$RELEASE"/chaincode/server
exit 0
fi
exit 1
編寫鏈碼作為外部服務運行
當前,將鏈碼作為外部服務運行模板只支持GO語言鏈碼shim.在Fabric v2.0,Go shim API添加了ChaincodeServer
類型。開發者可以使用它創建鏈碼服務。Invoke
和Query
API不受影響。開發者需要寫shim.ChaincodeServer
API,然后選擇構建鏈碼並在外部環境中運行。這里有一個簡單的鏈碼程序模板用來說明這種模式:
package main
import (
"fmt"
"github.com/hyperledger/fabric-chaincode-go/shim"
pb "github.com/hyperledger/fabric-protos-go/peer"
)
// SimpleChaincode 模板簡單鏈碼實現
type SimpleChaincode struct {
}
func (s *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
// 初始化代碼
}
func (s *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
// 調用代碼
}
//NOTE - ccid 和端點信息參數很難在這里編碼說明,可以通過多種標准方式指定
func main() {
//ccid 設計用來安裝鏈碼實例 (使用“peer lifecycle chaincode install <package>” 命令) for instance
ccid := "mycc:fcbf8724572d42e859a7dd9a7cd8e2efb84058292017df6e3d89178b64e6c831"
server := &shim.ChaincodeServer{
CCID: ccid,
Address: "myhost:9999"
CC: new(SimpleChaincode),
TLSProps: shim.TLSProperties{
Disabled: true,
},
}
err := server.Start()
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
將鏈碼作為外部服務運行關鍵的是使用shim.ChaincodeServer
.使用的新的鏈碼服務shim
APIshim.ChaincodeServer
屬性描述如下:
- CCID(string):CCID應該匹配
peer
節點上的鏈碼包。CCID
與被安裝的鏈碼關聯,在使用peer lifecycle chaincode install <package>
CLI命令返回。這可以在安裝后使用peer lifecycle chaincode queryinstalled
命令獲得。 - Address(string):鏈碼服務的監聽地址。
- CC(Chaincode):處理初始化和調用的鏈碼
- TLSProps(TLSProperties):鏈碼服務的TLS屬性。
- KaOpts(keepalive.ServerParameters):保持連接選項,默認為空
部署鏈碼
當GO語言鏈碼准備好部署后,可以通過Packageing chaincode部分解釋的內容對鏈碼進行打包。並通過chaincode lifecycle部分內容對鏈碼進行部署。
將鏈碼作為外部服務運行
根據指定的編寫鏈碼作為外部服務運行部分創建鏈碼,並選擇構建可運行的鏈碼環境如Kubernetes
或者直接在peer
主機上運行。
使用鏈碼作為外部服務模板,將不再要求在每一個節點上安裝鏈碼。當鏈碼端點在peer
節點上部署並運行后,可以繼續正常地實例化和調用鏈碼。