多个主机上的Hyperledger Fabric

Hyperledger Fabric是由Linux Foundation托管的业务区块链项目。它是一个“分布式总账解决方案平台,以模块化架构为基础,提供高度机密性,弹性好,灵活性和可扩展性。它旨在支持不同组件的可插拔实现,并适应整个经济生态系统中存在的复杂性和复杂性。“

我开始研究这项技术,作为探索区块链解决方案的PoC的一部分。Hyperledger Fabric有很好的文档,并有详细的入门教程。但是,它错过了分布式系统实现(在多个主机上部署)的最重要指南,这是分布式系统的本质。

是的,没有教程或指南可以帮助你跨多个主机部署网络。许多人在同一问题上围绕不同的论坛挣扎。我决定首先研究现有的样本,以了解超级分类网络的不同组件如何能够在单个主机上进行通信。

先决条件

本教程要求你首先从Hyperledger教程中关注Build You First Network。这是了解它如何连接并在单一主机模式下工作的重要步骤。此外,它还安装了对本教程非常重要的所有必要的先决条件和依赖项。

如果你想跳过上述教程并想要尝试这一点,则必须安装以下所述的所有先决条件:

在我们开始之前,如果你还没有这样做,你可能希望检查你是否已在将要开发区块链应用程序和/或运行Hyperledger Fabric的平台上安装了所有先决条件。

你还需要下载并安装Hyperledger Fabric Samples。你会注意到fabric-samples存储库中包含了许多样本。我们将使用第一个网络样本。我们现在打开那个子目录。

在安装了上述先决条件之后,在继续之前,让我们了解网络如何在单个主机上运行…

它如何在单个主机上运行…

Hyperledger Fabric依赖于基于docker的架构,超级分类网络的所有组件都在单独的容器中运行,而不能看到相邻的容器。为了使它们彼此通信,它们创建了一个网络,每个容器都附加到它上面。你可以在fabric-samples repo中“First Network”下的docker-compose-cli.yml中找到它。你会发现在docker-compse-cli.yml文件的开头,创建了网络byfn,然后所有容器都将自己附加到刚刚创建的网络上。

默认情况下,Compose为你的应用设置单个网络。服务的每个容器都加入默认网络,并且该网络上的其他容器都可以访问它们,并且它们可以在与容器名称相同的主机名上发现。

它将如何适用于多主机…

但是当我们跨多个主机工作时,容器无法相互通信。简而言之,我们需要找到一种方法来跨多个主机(PC)共享此网络(所有容器连接到的网络)。我猜测它可以通过使用docker swarm来实现。我找到了:

覆盖网络驱动程序在多个Docker守护程序主机之间创建分布式网络。该网络位于(覆盖)顶部,特定于主机的网络允许连接到它的容器(包括群服务容器)安全地通信。Docker透明地处理每个数据包与正确的Docker守护程序主机和正确的目标容器的路由。然后我的着眼点落在这里

我开始合并这些碎片并经过一些反复试验,我能够把它拉下来。要做到这一点,你需要

  • 首先初始化docker swarm模式(假设在PC 1上)。
  • 并使所有其他主机加入该群体作为manager(让我们说PC 2,PC3 ..)。
  • 创建一个超级网络,以便它可以在所有其他主机上共享。(其他主机可以看到网络的原因是它们是群组的一部分)

由于这是一个分布式系统,因此你需要多个主机(在我们的示例中为两台计算机)来验证该技术的分布式特性。假设你有两台PC,即PC1和PC2。

本教程仅适用于Linux,为什么?

目前,你无法单独使用Docker for Mac或Docker for Windows来测试多节点群。

网络拓扑结构

因此,我们要构建的网络将具有以下组件。对于这个例子,我们使用两台PC(PC1和PC2):

    1. 证书颁发机构(CA)—— PC1
    1. Orderer —— PC1
    1. 1 PEER(peer0)on —— PC1
    1. 1 PEER(peer1)on —— PC2
    1. CLI on —— PC2

在拓扑图里:

在你开始之前

  • 初始化一个群:( docker swarm文档获取更多信息)
1
$ docker swarm init
  • 加入swarm与其他主机作为经理(PC1将创建swarm,PC2将加入它)

PC1:

1
$ docker swarm join-token manager

它会输出这样的内容:

1
docker swarm join — token SWMTKN-1–3as8cvf3yxk8e7zj98954jhjza3w75mngmxh543llgpo0c8k7z-61zyibtaqjjimkqj8p6t9lwgu 172.16.0.153:2377

我们将复制它(终端上的那个,而不是上面的那个)并在PC2终端上执行它以使其加入PC1

在PC2上使用上一个命令的输出命令

  • 创建一个网络(在我的情况下为my-net)——PC1
1
$ docker network create --attachable --driver overlay my-net
  • 在两台PC上克隆这个repo,即PC1和PC2。
1
$ git clone https://github.com/wahabjawed/Build-Multi-Host-Network-Hyperledger.git
  • 生成网络工件(加密资源)——PC1
1
2
3
$ cd Build-Multi-Host-Network-Hyperledger/

$ ./bmhn.sh

这将在crypto-configchannel-artifacts文件夹中为你生成网络工件。你必须在PC2上复制这些文件夹,以便两个项目都具有相同的加密资源。重要的是,两台PC必须具有相同的加密资源,否则网络将无法通信。

设置网络

在PC1上:

以下脚本将在PC1上运行。在单独的终端中执行每个命令。

在执行任何脚本之前,还要确保你处于Build-Multi-Host-Network-Hyperledger/文件夹中。脚本使用Build-Multi-Host-Network-Hyperledger文件夹中的文件,如果无法找到它,则会抛出错误。

1.CA服务器:

你将在PC1上执行此命令。在执行此操作之前,将{put the secret of secret key}替换为密钥的名称。你可以在/crypto-config/peerOrganizations/org1.example.com/ca/下找到它。

1
docker run --rm -it --network="my-net" --name ca.example.com -p 7054:7054 -e FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server -e FABRIC_CA_SERVER_CA_NAME=ca.example.com -e FABRIC_CA_SERVER_CA_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem -e FABRIC_CA_SERVER_CA_KEYFILE=/etc/hyperledger/fabric-ca-server-config/{put the name of secret key} -v $(pwd)/crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config -e CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=hyp-net hyperledger/fabric-ca sh -c 'fabric-ca-server start -b admin:adminpw -d'

2.Orderer

执行此命令以在PC1上生成Orderer:

1
docker run --rm -it --network="my-net" --name orderer.example.com -p 7050:7050 -e ORDERER_GENERAL_LOGLEVEL=debug -e ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 -e ORDERER_GENERAL_LISTENPORT=7050 -e ORDERER_GENERAL_GENESISMETHOD=file -e ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block -e ORDERER_GENERAL_LOCALMSPID=OrdererMSP -e ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp -e ORDERER_GENERAL_TLS_ENABLED=false -e CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=my-net -v $(pwd)/channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block -v $(pwd)/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp -w /opt/gopath/src/github.com/hyperledger/fabric hyperledger/fabric-orderer orderer

3.CouchDB 0 —— Peer 0

此命令将生成一个couchDB实例,peer0将使用该实例存储对等分类帐。

1
docker run --rm -it --network="my-net" --name couchdb0 -p 5984:5984 -e COUCHDB_USER= -e COUCHDB_PASSWORD= -e CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=my-net hyperledger/fabric-couchdb

4.Peer 0

现在我们执行此命令来生成peer0

1
docker run --rm -it --link orderer.example.com:orderer.example.com --network="my-net" --name peer0.org1.example.com -p 8051:7051 -p 8053:7053 -e CORE_LEDGER_STATE_STATEDATABASE=CouchDB -e CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb0:5984 -e CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME= -e CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= -e CORE_PEER_ADDRESSAUTODETECT=true -e CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock -e CORE_LOGGING_LEVEL=DEBUG -e CORE_PEER_NETWORKID=peer0.org1.example.com -e CORE_NEXT=true -e CORE_PEER_ENDORSER_ENABLED=true -e CORE_PEER_ID=peer0.org1.example.com -e CORE_PEER_PROFILE_ENABLED=true -e CORE_PEER_COMMITTER_LEDGER_ORDERER=orderer.example.com:7050 -e CORE_PEER_GOSSIP_IGNORESECURITY=true -e CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=my-net -e CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051 -e CORE_PEER_TLS_ENABLED=false -e CORE_PEER_GOSSIP_USELEADERELECTION=false -e CORE_PEER_GOSSIP_ORGLEADER=true -e CORE_PEER_LOCALMSPID=Org1MSP -v /var/run/:/host/var/run/ -v $(pwd)/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp -w /opt/gopath/src/github.com/hyperledger/fabric/peer hyperledger/fabric-peer peer node start

在PC2上:

以下命令将在PC2上执行。

在执行任何脚本之前,请确保你处于Build-Multi-Host-Network-Hyperledger文件夹中。脚本使用Build-Multi-Host-Network-Hyperledger文件夹中的文件,如果无法找到它,则会抛出错误。

5.CouchDB 1 —— for Peer 1

此命令将生成一个couchDB实例,peer1将使用该实例存储对等分类帐。 我们将在PC2上的一个单独终端中执行此操作

1
docker run --rm -it --network="my-net" --name couchdb1 -p 6984:5984 -e COUCHDB_USER= -e COUCHDB_PASSWORD= -e CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=my-net hyperledger/fabric-couchdb

6.Peer 1

我们将在PC2上的一个单独终端中执行此操作以生成peer1。

1
docker run --rm -it --network="my-net" --link orderer.example.com:orderer.example.com --link peer0.org1.example.com:peer0.org1.example.com --name peer1.org1.example.com -p 9051:7051 -p 9053:7053 -e CORE_LEDGER_STATE_STATEDATABASE=CouchDB -e CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb1:5984 -e CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME= -e CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= -e CORE_PEER_ADDRESSAUTODETECT=true -e CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock -e CORE_LOGGING_LEVEL=DEBUG -e CORE_PEER_NETWORKID=peer1.org1.example.com -e CORE_NEXT=true -e CORE_PEER_ENDORSER_ENABLED=true -e CORE_PEER_ID=peer1.org1.example.com -e CORE_PEER_PROFILE_ENABLED=true -e CORE_PEER_COMMITTER_LEDGER_ORDERER=orderer.example.com:7050 -e CORE_PEER_GOSSIP_ORGLEADER=true -e CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:7051 -e CORE_PEER_GOSSIP_IGNORESECURITY=true -e CORE_PEER_LOCALMSPID=Org1MSP -e CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=my-net -e CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051 -e CORE_PEER_GOSSIP_USELEADERELECTION=false -e CORE_PEER_TLS_ENABLED=false -v /var/run/:/host/var/run/ -v $(pwd)/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp:/etc/hyperledger/fabric/msp -w /opt/gopath/src/github.com/hyperledger/fabric/peer hyperledger/fabric-peer peer node start

7. CLI

在PC2上的不同终端中执行以下脚本以生成CLI。

1
docker run --rm -it --network="my-net" --name cli --link orderer.example.com:orderer.example.com --link peer0.org1.example.com:peer0.org1.example.com --link peer1.org1.example.com:peer1.org1.example.com -p 12051:7051 -p 12053:7053 -e GOPATH=/opt/gopath -e CORE_PEER_LOCALMSPID=Org1MSP -e CORE_PEER_TLS_ENABLED=false -e CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock -e CORE_LOGGING_LEVEL=DEBUG -e CORE_PEER_ID=cli -e CORE_PEER_ADDRESS=peer0.org1.example.com:7051 -e CORE_PEER_NETWORKID=cli -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp -e CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=my-net  -v /var/run/:/host/var/run/ -v $(pwd)/chaincode/:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go -v $(pwd)/crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ -v $(pwd)/scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/ -v $(pwd)/channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts -w /opt/gopath/src/github.com/hyperledger/fabric/peer hyperledger/fabric-tools /bin/bash -c './scripts/script.sh'

如果你看到这一点,则表示该脚本已被执行:

这将安装CLI容器并将执行脚本:

1
'./scripts/script.sh'

该脚本将:

  • 创建频道;在我们的例子中是mychannel
  • 使peer0和peer1加入该频道。
  • 成功加入频道后,脚本将更新对等网络的锚点(在我们的例子中为peer0)。
  • 在两个对等端上安装链代码。

现在我们的网络正在运行,让我们测试一下。现在我们将从PC2调用和查询两个对等体上的区块链代码。

我们开始做吧。

测试网络

Step 1. Bin/Bash CLI——PC2

我们将再次在PC2上生成cli容器,但这次我们将执行它:

1
docker run --rm -it --network="my-net" --name cli --link orderer.example.com:orderer.example.com --link peer0.org1.example.com:peer0.org1.example.com --link peer1.org1.example.com:peer1.org1.example.com -p 12051:7051 -p 12053:7053 -e GOPATH=/opt/gopath -e CORE_PEER_LOCALMSPID=Org1MSP -e CORE_PEER_TLS_ENABLED=false -e CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock -e CORE_LOGGING_LEVEL=DEBUG -e CORE_PEER_ID=cli -e CORE_PEER_ADDRESS=peer0.org1.example.com:7051 -e CORE_PEER_NETWORKID=cli -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp -e CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=my-net  -v /var/run/:/host/var/run/ -v $(pwd)/chaincode/:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go -v $(pwd)/crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ -v $(pwd)/scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/ -v $(pwd)/channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts -w /opt/gopath/src/github.com/hyperledger/fabric/peer hyperledger/fabric-tools /bin/bash

执行命令后必须看到这一点:

1
root@a14d67c2dbb5:/opt/gopath/src/github.com/hyperledger/fabric/peer#

现在你已进入CLI容器,我们将执行命令以实例化,调用和查询此容器中的区块链代码。

Step 2.在Peer0上实例化Chaincode

要在peer0上实例化链代码,我们需要先设置一些环境变量。将以下行粘贴在cli终端中。

1
2
3
4
5
6
# Environment variables for PEER0

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_LOCALMSPID="Org1MSP"
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_ADDRESS=peer0.org1.example.com:7051

之后我们将初始化区块链码。执行以下命令以实例化作为步骤1的一部分安装的区块链代码。

1
$ peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')"

这将实例化chiancode并用a=100b=200填充它。

此时,随着你的分类帐的填充,你可以查看(在PC1上的浏览器上打开它):

Peer0(PC 1):http://localhost:5984/_utils/#/database/mychannel/_all_docs

Peer1(PC 2):http://localhost:5984/_utils/#/database/mychannel/_all_docs

以上是couchDB Web界面端点。由于数据以二进制形式保存,因此你无法找到确切的值(而是会找到哈希值),但会看到包含myacc的键的记录。

OR

让我们查询它并查看结果。我们将在peer1上查询它。

Step 3.查询Peer1上的Chaincode

要查询peer1上的区块链代码,我们首先需要设置一些环境变量。将以下行粘贴在PC2上的cli终端中:

1
2
3
4
5
# Environment variables for PEER1
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_LOCALMSPID="Org1MSP"
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_ADDRESS=peer1.org1.example.com:7051

让我们查询a的值,以确保区块链代码已正确实例化并且沙发数据库已填充。查询的语法如下:(在cli终端中执行)并等待一段时间:

1
$ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'

它会带来:

1
Query Result: 100

Step 4.在Peer0上调用Chaincode

要在peer0上调用链代码,我们需要先设置一些环境变量。将以下行粘贴在PC2上的cli终端中:

1
2
3
4
5
# Environment variables for PEER0
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_LOCALMSPID="Org1MSP"
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_ADDRESS=peer0.org1.example.com:7051

现在让我们从ab移动10。此交易将删除一个新块并更新couch数据库。调用的语法如下:(在PC2上的cli终端中执行):

1
$ peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'

Step 5.查询Chaincode

让我们确认我们之前的调用是否正确执行。我们使用值100初始化了键a,并在之前的调用中删除了10。因此,对a的查询应该显示90。查询的语法如下(我们在peer0上查询所以不需要更改环境变量):

1
2
# be sure to set the -C and -n flags appropriately
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'

我们应该看到以下内容:

1
Query Result: 90

随意重新开始并操纵键值对和后续调用。

下一步是什么…

在超级账本结构教程上实现区块链代码执行仍然处于开发模式,这就是为什么我一直在使用HProxy来实现负载平衡区块链代码执行以使其生产就绪。

此外,我一直在使用区块链资源管理器来监控网络中不同的矩阵,即区块,交易,吞吐量,活动节点等。

我会尽快发布。

快乐区块链:)

======================================================================

分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程:

  • java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
  • php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。
  • python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
  • 以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。
  • 以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
  • C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。
  • EOS教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。
  • java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
  • php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。
  • tendermint区块链开发详解,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。

汇智网原创翻译,转载请标明出处。这里是多个主机上的Hyperledger Fabric