Raft是Hyperledger Fabric 1.4.1中新增的排序服務子產品,這個教程将介紹如何部署一個基于Raft排序服務的多機Fabric網絡。
相關教程推薦:
1、用Raft排序服務啟動byfn示例
BYFN是學習Hyperledger Fabric的一個很好的例子:它包含了Fabric網絡的所有元素,并且在byfn.sh中完整表現出來。當我們不加任何參數運作這個腳本時,它将啟動一個包含2個機構、4個peer和1個orderer(使用solo排序)的Fabric網絡。byfn.sh的參數
-o
用來指定排序服務的類型:
./byfn.sh up -o <kafka | etcdraft>
最新的BYFN網絡設計中包含了5個orderer的密碼學資料。如果使用Solo或Kafka排序服務,将值運作第一個Orderer(參見docker-compose-cli.yaml中的定義)。
當我們指定raft作為排序服務時的一個差別之處在于,使用configtxgen生成創世區塊我們需要指定configtx.yaml中的SampleMultiNodeEtcdRaft配置端。其他的操作都保持不變。
最後,我們還需要啟動其他4個orderer,這些内容在docker-compose-etcdraft2.yaml中定義。
下面時基于raft排序的BYFN網絡啟動後的情況,你可以看到有5個orderer在運作:

下面是基于Raft排序服務的BYFN網絡的拓撲示意圖:
在下面的内容中,我們将不再使用BYFN腳本,而是從零開始來學習如何建構多主機的Raft排序的Fabric網絡。
2、Hyperledger Fabric多機部署的不同方案
由于Hyperledger Fabric的元件以容器形式部署,當這些容器都在本機時會很順利的工作。但是當這些容器需要運作在不同的主機上時,我們需要找出讓它們彼此通信的辦法。
雖然Hyperledger Fabric官方沒有給出正式的推薦方案,目前大緻有三種方案:
使用靜态IP:通過指定容器運作的主機IP,容器之間就可以彼此通信。可以在docker-compose檔案中使用extra_hosts方法來指定主機IP,當容器運作後,就可以在/etc/hosts檔案中看到這些項。這一方案容易了解,我們也不需要依賴于外部元件,缺點在于所有的東西都是靜态配置的,不利于需要動态修改配置的應用場景。
使用docker swarm:Docker Swarm是Docker環境中的原生容器編排服務。簡而言之,Docker Swarm為跨主機的容器提供了一個疊加網絡層,使容器彼此之間能夠通信,就像在一台主機上一樣。這一方案的好處在于原始的配置隻需要簡單修改就可以使用,也不需要在配置中寫死像IP位址這樣的靜态資訊。缺點在于需要依賴外部元件Docker Swarm。在這個教程中我們将使用這一方案。
使用Kubernetes:k8s使目前最流行的容器編排工具,其機制類似于Docker Swarm。我們已經注意到有一些教程嘗試利用k8s來進行fabric的多機部署,但是使用k8s的難度要明顯高于前兩種方案。
3、Fabrc Raft多機示範環境搭建
我們需要将容器分發到4個主機,本教程使用AWS上的4個EC2執行個體,但是并不使用AWS提供的特别功能,僅僅是用它來運作Ubuntu以及必要的軟體,采用公共IP進行通信。當然你可以可以選擇其他的雲服務提供商。
在Fabric網絡啟動運作後,我們将使用Fabcar鍊碼進行測試。總體流程如下:
- 啟動AWS EC2執行個體,安裝必要的鏡像和工具。
- 建構一個疊加網絡,将4個主機都加入該網絡
-
在主機1上準備所有資料,包括密碼學資料、通道配置交易、每個節點的docker-compose
檔案等。然後拷貝到其他主機。
- 使用docker-compose啟動所有元件
- 建立通道mychannel并将所有peer加入該通道
- 安裝并執行個體化Fabcar鍊碼
- 調用查詢鍊碼方法
4、Fabric Raft多機示範
4.1 啟動主機
本教程使用AWS EC2 t2.small執行個體,使用fabric 1.4.4。注意在示範中我們使用了簡化的全開放安全組,在生産環境中你應當根據自己的需求來決定開放哪些端口:
4.2 使用Docker Swarm建構疊加網絡
現在我們可以打開4個終端,分别對應每個主機:
ssh -i <key> ubuntu@<public IP>
從Host 1執行如下指令:
docker swarm init --advertise-addr <host-1 ip address>
docker swarm join-token manager
運作結果如下:
使用最後的輸出,将其他節點以管理者身份加入swarm。
從host 2/3/4執行如下指令:
<output from join-token manager> --advertise-addr <host n ip>
最後,我們添加一個疊加網絡,該網絡将用于下面的示範,這一步的操作隻需要在一個節點上執行。如果Docker Swarm正常工作,所有的節點都會加入這個疊加網絡。
從host 1建立疊加網絡first-network:
docker network create --attachable --driver overlay first-networkdocker network ls
在其他主機上,我們可以看到這個網絡:
現在已經建構好了疊加網絡,這些資訊将在稍後用于docker-compose檔案。
4.3 在host 1上準備資料
一個關鍵的環節時確定所有的Farbic成員使用相同的密碼學資料。我們将使用host 1來建立這些密碼學資料,然後拷貝到其他主機。
理論上,我們隻需要確定個體身份(證書和簽名私鑰)遵循所要求的規範。一個機構的證書應當由同一個CA簽發 —— 例如org1的證書應當由ca.org1簽發。出于簡化目的,在本教程中,我們在host 1上建立所有的密碼學資料,然後将整個目錄拷貝到其他主機。
首先進入fabric-samples目錄,然後建立一個raft-4node-swarm目錄。
在host 1上執行如下指令:
cd fabric-samples
mkdir raft-4node-swarm
cd raft-4node-swarm
直接從first-network拷貝crypto-config.yaml和configtx.yaml檔案:
cp ../first-network/crypto-config.yaml .
cp ../first-network/configtx.yaml .
然後生成必要的密碼學資料:
../bin/cryptogen generate --config=./crypto-config.yaml
export FABRIC_CFG_PATH=$PWD
mkdir channel-artifacts
../bin/configtxgen -profile SampleMultiNodeEtcdRaft -outputBlock ./channel-artifacts/genesis.block
../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP
現在我們為所有主機準備docker-compose檔案,主要基于BYFN中的檔案,需要建立6個docker-compose檔案以及一個env檔案:
- base/peer-base.yaml
- base/docker-compose-peer.yaml
- host1.yaml
- host2.yaml
- host3.yaml
- host4.yaml
- .env
4.3.1 base/peer-base.yaml
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2'
services:
peer-base:
image: hyperledger/fabric-peer:$IMAGE_TAG
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
# the following setting starts chaincode containers on the same
# bridge network as the peers
# https://docs.docker.com/compose/networking/
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=first-network
- FABRIC_LOGGING_SPEC=INFO
#- FABRIC_LOGGING_SPEC=DEBUG
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_GOSSIP_USELEADERELECTION=true
- CORE_PEER_GOSSIP_ORGLEADER=false
- CORE_PEER_PROFILE_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
orderer-base:
image: hyperledger/fabric-orderer:$IMAGE_TAG
environment:
- FABRIC_LOGGING_SPEC=INFO
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
- ORDERER_GENERAL_GENESISMETHOD=file
- ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
- ORDERER_GENERAL_LOCALMSPID=OrdererMSP
- ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
# enabled TLS
- ORDERER_GENERAL_TLS_ENABLED=true
- ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
- ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
- ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
- ORDERER_KAFKA_TOPIC_REPLICATIONFACTOR=1
- ORDERER_KAFKA_VERBOSE=true
- ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt
- ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key
- ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
working_dir: /opt/gopath/src/github.com/hyperledger/fabric
command: orderer
4.3.2 base/docker-compose-base.yaml
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2'
services:
orderer.example.com:
container_name: orderer.example.com
extends:
file: peer-base.yaml
service: orderer-base
volumes:
- ../channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
- ../crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp
- ../crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/:/var/hyperledger/orderer/tls
- orderer.example.com:/var/hyperledger/production/orderer
ports:
- 7050:7050
peer0.org1.example.com:
container_name: peer0.org1.example.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.org1.example.com
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
- CORE_PEER_LISTENADDRESS=0.0.0.0:7051
- CORE_PEER_CHAINCODEADDRESS=peer0.org1.example.com:7052
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
- CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls
- peer0.org1.example.com:/var/hyperledger/production
ports:
- 7051:7051
peer1.org1.example.com:
container_name: peer1.org1.example.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer1.org1.example.com
- CORE_PEER_ADDRESS=peer1.org1.example.com:7051
- CORE_PEER_LISTENADDRESS=0.0.0.0:7051
- CORE_PEER_CHAINCODEADDRESS=peer1.org1.example.com:7052
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls:/etc/hyperledger/fabric/tls
- peer1.org1.example.com:/var/hyperledger/production
ports:
- 7051:7051
peer0.org2.example.com:
container_name: peer0.org2.example.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.org2.example.com
- CORE_PEER_ADDRESS=peer0.org2.example.com:7051
- CORE_PEER_LISTENADDRESS=0.0.0.0:7051
- CORE_PEER_CHAINCODEADDRESS=peer0.org2.example.com:7052
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org2.example.com:7051
- CORE_PEER_LOCALMSPID=Org2MSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls:/etc/hyperledger/fabric/tls
- peer0.org2.example.com:/var/hyperledger/production
ports:
- 7051:7051
peer1.org2.example.com:
container_name: peer1.org2.example.com
extends:
file: peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer1.org2.example.com
- CORE_PEER_ADDRESS=peer1.org2.example.com:7051
- CORE_PEER_LISTENADDRESS=0.0.0.0:7051
- CORE_PEER_CHAINCODEADDRESS=peer1.org2.example.com:7052
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.example.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:7051
- CORE_PEER_LOCALMSPID=Org2MSP
volumes:
- /var/run/:/host/var/run/
- ../crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/msp:/etc/hyperledger/fabric/msp
- ../crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls:/etc/hyperledger/fabric/tls
- peer1.org2.example.com:/var/hyperledger/production
ports:
- 7051:7051
4.3.3 host1.yaml
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2'
volumes:
orderer.example.com:
orderer5.example.com:
peer0.org1.example.com:
networks:
byfn:
external:
name: first-network
services:
orderer.example.com:
extends:
file: base/docker-compose-base.yaml
service: orderer.example.com
container_name: orderer.example.com
networks:
- byfn
orderer5.example.com:
extends:
file: base/peer-base.yaml
service: orderer-base
container_name: orderer5.example.com
networks:
- byfn
volumes:
- ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
- ./crypto-config/ordererOrganizations/example.com/orderers/orderer5.example.com/msp:/var/hyperledger/orderer/msp
- ./crypto-config/ordererOrganizations/example.com/orderers/orderer5.example.com/tls/:/var/hyperledger/orderer/tls
- orderer5.example.com:/var/hyperledger/production/orderer
ports:
- 8050:7050
peer0.org1.example.com:
container_name: peer0.org1.example.com
extends:
file: base/docker-compose-base.yaml
service: peer0.org1.example.com
networks:
- byfn
cli:
container_name: cli
image: hyperledger/fabric-tools:$IMAGE_TAG
tty: true
stdin_open: true
environment:
- SYS_CHANNEL=$SYS_CHANNEL
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
#- FABRIC_LOGGING_SPEC=DEBUG
- FABRIC_LOGGING_SPEC=INFO
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash
volumes:
- /var/run/:/host/var/run/
- ./../chaincode/:/opt/gopath/src/github.com/chaincode
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on:
- orderer.example.com
- peer0.org1.example.com
networks:
- byfn
4.3.4 host2.yaml
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2'
volumes:
orderer2.example.com:
peer1.org1.example.com:
networks:
byfn:
external:
name: first-network
services:
orderer2.example.com:
extends:
file: base/peer-base.yaml
service: orderer-base
container_name: orderer2.example.com
networks:
- byfn
volumes:
- ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
- ./crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/msp:/var/hyperledger/orderer/msp
- ./crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/:/var/hyperledger/orderer/tls
- orderer2.example.com:/var/hyperledger/production/orderer
ports:
- 7050:7050
peer1.org1.example.com:
container_name: peer1.org1.example.com
extends:
file: base/docker-compose-base.yaml
service: peer1.org1.example.com
networks:
- byfn
4.3.5 host3.yaml
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2'
volumes:
orderer3.example.com:
peer0.org2.example.com:
networks:
byfn:
external:
name: first-network
services:
orderer3.example.com:
extends:
file: base/peer-base.yaml
service: orderer-base
container_name: orderer3.example.com
networks:
- byfn
volumes:
- ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
- ./crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/msp:/var/hyperledger/orderer/msp
- ./crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/:/var/hyperledger/orderer/tls
- orderer3.example.com:/var/hyperledger/production/orderer
ports:
- 7050:7050
peer0.org2.example.com:
container_name: peer0.org2.example.com
extends:
file: base/docker-compose-base.yaml
service: peer0.org2.example.com
networks:
- byfn
4.3.6 host4.yaml
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2'
volumes:
orderer4.example.com:
peer1.org2.example.com:
networks:
byfn:
external:
name: first-network
services:
orderer4.example.com:
extends:
file: base/peer-base.yaml
service: orderer-base
container_name: orderer4.example.com
networks:
- byfn
volumes:
- ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
- ./crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/msp:/var/hyperledger/orderer/msp
- ./crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/:/var/hyperledger/orderer/tls
- orderer4.example.com:/var/hyperledger/production/orderer
ports:
- 7050:7050
peer1.org2.example.com:
container_name: peer1.org2.example.com
extends:
file: base/docker-compose-base.yaml
service: peer1.org2.example.com
networks:
- byfn
4.3.7 .env
COMPOSE_PROJECT_NAME=net
IMAGE_TAG=latest
SYS_CHANNEL=byfn-sys-channel
下面是目錄中的内容:
下面是針對BYFN中的檔案所作的修改:
-
base/peer-base.yaml
中,CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE修改為
我們之前建立的疊加網絡first-network
-
base/docker-compose-base.yaml
中,由于所有的peers都在不同的主機上,我們
将端口映射改回7051:7051。在每個peer的環境變量中也進行了相應的修改。
- 在所有的
檔案中,我們添加疊加網絡first-networkhostn.yaml
現在我們在host 1上準備好了所有資料,将該目錄拷貝到其他主機。由于不能跨EC2執行個體拷貝檔案,我們使用本地機器進行橋接操作:
# on Host 1
cd ..
tar cf raft-4node-swarm.tar raft-4node-swarm/# on my localhost
scp -i <key> ubuntu@<Host 1 IP>:/home/ubuntu/fabric-samples/raft-4node-swarm.tar .
scp -i <key> raft-4node-swarm.tar ubuntu@<Host 2, 3 and 4 IP>:/home/ubuntu/fabric-samples/# on Host 2, 3 and 4
cd fabric-samples
tar xf raft-4node-swarm
cd raft-4node-swarm
現在所有的節點都有了同樣的密碼學資料和docker-compose檔案,我們可以啟動容器了。
4.4 分别啟動各主機上的容器
我們使用docker-compose啟動全部主機:
# on Host 1, 2, 3 and 4, bring up corresponding yaml file
docker-compose -f hostn.yaml up -d
4.5 建立通道并加入peer
由于我們僅在host 1上由指令行CLI,是以從host 1的終端執行所有的指令。
為mychannel通道建立創世區塊:
docker exec cli peer channel create -o orderer.example.com:7050 -c mychannel \
-f ./channel-artifacts/channel.tx --tls \
--cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
将peer0.org1加入mychannel:
docker exec cli peer channel join -b mychannel.block
将peer1.org1加入mychannel:
docker exec -e CORE_PEER_ADDRESS=peer1.org1.example.com:7051 \
-e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt \
cli peer channel join -b mychannel.block
将peer0.org2加入mychannel:
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
-e CORE_PEER_ADDRESS=peer0.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" \
-e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
cli peer channel join -b mychannel.block
将peer1.org2 加入mychannel:
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
-e CORE_PEER_ADDRESS=peer1.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" \
-e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt \
cli peer channel join -b mychannel.block
4.6 安裝并執行個體化Fabcar鍊碼
從host 1的終端将Fabcar鍊碼安裝到所有peer節點:
# to peer0.org1
docker exec cli peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/fabcar/go/
# to peer1.org1
docker exec -e CORE_PEER_ADDRESS=peer1.org1.example.com:7051 \
-e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt \
cli peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/fabcar/go/
# to peer0.org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
-e CORE_PEER_ADDRESS=peer0.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" \
-e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
cli peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/fabcar/go/
# to peer1.org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
-e CORE_PEER_ADDRESS=peer1.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" \
-e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt \
cli peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/fabcar/go/
在通道mychannle執行個體化Fabcar鍊碼:
docker exec cli peer chaincode instantiate -o orderer.example.com:7050 --tls \
--cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
-C mychannel -n mycc -v 1.0 -c '{"Args":[]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"
4.7 鍊碼調用與查詢
首先調用
initLedger
方法将10個車輛記錄載入賬本。
在peer0.org1上執行:
docker exec cli peer chaincode invoke -o orderer.example.com:7050 --tls true \
--cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
-C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 \
--tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \
--peerAddresses peer0.org2.example.com:7051 \
--tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
-c '{"Args":["initLedger"]}'
現在可以從4個不同的peer節點查詢車輛記錄:
# from peer0.org1
docker exec cli peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'
# from peer1.org1
docker exec -e CORE_PEER_ADDRESS=peer1.org1.example.com:7051 \
-e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt \
cli peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'
# from peer0.org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
-e CORE_PEER_ADDRESS=peer0.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" \
-e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
cli peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'
# from peer1.org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
-e CORE_PEER_ADDRESS=peer1.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" \
-e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt \
cli peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'
現在我們使用orderer3.example.com來調用 changeCarOwner,并在執行
後進行查詢:
docker exec cli peer chaincode invoke -o orderer3.example.com:7050 --tls true \
--cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
-C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 \
--tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \
--peerAddresses peer0.org2.example.com:7051 \
--tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
-c '{"Args":["changeCarOwner","CAR0","KC"]}'
# from peer0.org1
docker exec cli peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'
# from peer1.org2
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp \
-e CORE_PEER_ADDRESS=peer1.org2.example.com:7051 -e CORE_PEER_LOCALMSPID="Org2MSP" \
-e CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt \
cli peer chaincode query -n mycc -C mychannel -c '{"Args":["queryCar","CAR0"]}'
你可以使用其他的orderer進行鍊碼調用。由于這些排序節點構成了raft叢集,你
應該得到同樣的結果,這表示排序節點叢集工作正常。
4.8 清理環境
要清理運作環境,使用docker-compose将容器停掉并移除即可:
# each host
docker-compose -f noden.yaml down -v
5、總結
在本教程中,我們基于BYFN示例進行修改,建構了一個基于Raft排序叢集的
Hyperledger Fabric網絡,使用Docker Swarm來實作多主機容器的通信。
原文連結:
Hyperledger Fabric Raft排序多機部署 - 彙智網