文章目录
1. byfn测试网络的启动
1.1 准备二进制可执行文件
- 在fabric目录中执行
make native
命令可编译出二进制可执行文件,然后将fabric/build/bin目录拷贝到fabric-samples目录中; - 但是最新的fabric版本在可能会造成后面运行
./byfn generate
报错的问题。因此可考虑直接从github上下载稳定的二进制可执行文件,运行命令wget https://github.com/hyperledger/fabric/releases/download/v2.0.1/hyperledger-fabric-linux-amd64-2.0.1.tar.gz
,解压后同样将bin目录拷贝到fabric-samples目录中。
两种方法均可得到二进制可执行文件,如下图所示:
1.2 构建docker镜像
在fabric目录中执行make docker
命令,可得到所需的相关镜像。
从Fabric2.0开始docker镜像将基于Alpine Linux,这是一种面向安全的轻量级Linux发行版,只占5MB左右的空间,且更加安全可靠。另外Alpine Linux还提供了自己的包管理工具apk,我们在构建docker镜像过程中存在“apk add”的动作,可能会有从“dl-cdn.alpinelinux.org/alpine/v3.10”下载包失败的问题,这是由于在中国大陆无法连接官方的更新源,因此可考虑在所有Dockerfile中修改为使用阿里云的更新源:
FROM alpine:${ALPINE_VER} as base
RUN echo "#aliyun" > /etc/apk/repositories
RUN echo "https://mirrors.aliyun.com/alpine/v3.10/main/" >> /etc/apk/repositories
RUN echo "https://mirrors.aliyun.com/alpine/v3.10/community/" >> /etc/apk/repositories
最终构建成功,将会得到这些镜像:
1.3 启动测试网络
在fabric-samples/first-network目录中,执行./byfn.sh up
命令启动测试网络,默认会生成crypto-config和channel-artifacts目录中的文件。最后控制台输出如下内容,表示运行成功。
2. networkUp 脚本分析
执行“./byfn.sh up”命令调用的就是networkUp,脚本逻辑步骤如下:
- 如果crypto-config目录不存在,networkUp会先执行generateCerts生成证书与密钥,以及generateChannelArtifacts生成创世区块、用户channel配置交易、 anchor peer节点更新交易;
- compose文件包括docker-compose-cli.yaml、docker-compose-etcdraft2.yaml;如果指定了CA,还将包括docker-compose-ca.yaml;如果指定了couchdb,还将包括docker-compose-couch.yaml;使用docker-compose构建和启动容器;
- 下载abstore链码的依赖包;
- 执行容器cli中的script.sh脚本,参数包括:
channel名称(CHANNEL_NAME):mychannel
命令延迟时间(DELAY):3秒
链码语言(CC_SRC_LANGUAGE):go
cli等待其他容器的超时(TIMEOUT):10秒
# Generate the needed certificates, the genesis block and start the network.
function networkUp() {
checkPrereqs
# generate artifacts if they don't exist
if [ ! -d "crypto-config" ]; then
generateCerts
generateChannelArtifacts
fi
COMPOSE_FILES="-f ${COMPOSE_FILE} -f ${COMPOSE_FILE_RAFT2}"
if [ "${CERTIFICATE_AUTHORITIES}" == "true" ]; then
COMPOSE_FILES="${COMPOSE_FILES} -f ${COMPOSE_FILE_CA}"
export BYFN_CA1_PRIVATE_KEY=$(cd crypto-config/peerOrganizations/org1.example.com/ca && ls *_sk)
export BYFN_CA2_PRIVATE_KEY=$(cd crypto-config/peerOrganizations/org2.example.com/ca && ls *_sk)
fi
if [ "${IF_COUCHDB}" == "couchdb" ]; then
COMPOSE_FILES="${COMPOSE_FILES} -f ${COMPOSE_FILE_COUCH}"
fi
IMAGE_TAG=$IMAGETAG docker-compose ${COMPOSE_FILES} up -d 2>&1
docker ps -a
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to start network"
exit 1
fi
echo "Sleeping 15s to allow Raft cluster to complete booting"
sleep 15
if [ "${NO_CHAINCODE}" != "true" ]; then
echo Vendoring Go dependencies ...
pushd ../chaincode/abstore/go
GO111MODULE=on go mod vendor
popd
echo Finished vendoring Go dependencies
fi
# now run the end to end script
docker exec cli scripts/script.sh $CHANNEL_NAME $CLI_DELAY $CC_SRC_LANGUAGE $CLI_TIMEOUT $VERBOSE $NO_CHAINCODE
if [ $? -ne 0 ]; then
echo "ERROR !!!! Test failed"
exit 1
fi
}
下面将对networkUp中的一些具体细节进行剖析。
3. 创建初始文件与配置分析
3.1 generateCerts 生成证书
generateCerts使用cryptogen工具生成组织证书,主要包括两个步骤:
cryptogen generate --config=./crypto-config.yaml
将根据crypto-config.yaml中的配置生成证书./ccp-generate.sh
生成调用SDK的相关配置文件。
# Generates Org certs using cryptogen tool
function generateCerts() {
which cryptogen
if [ "$?" -ne 0 ]; then
echo "cryptogen tool not found. exiting"
exit 1
fi
echo
echo "##########################################################"
echo "##### Generate certificates using cryptogen tool #########"
echo "##########################################################"
if [ -d "crypto-config" ]; then
rm -Rf crypto-config
fi
set -x
cryptogen generate --config=./crypto-config.yaml
res=$?
set +x
if [ $res -ne 0 ]; then
echo "Failed to generate certificates..."
exit 1
fi
echo
echo "Generate CCP files for Org1 and Org2"
./ccp-generate.sh
}
- crypto-config.yaml中的配置分为OrdererOrgs和PeerOrgs两部分。
- OrdererOrgs中定义管理orderer节点的组织,里面配置了5个排序节点,采用Specs配置模式,全名为:{{.Hostname}}.{{.Domain}},比如orderer.example.com。
OrdererOrgs:
- Name: Orderer
Domain: example.com
Specs:
- Hostname: orderer
- Hostname: orderer2
- Hostname: orderer3
- Hostname: orderer4
- Hostname: orderer5
- 也可重写限定域名CommonName,默认值为Hostname,例如可以这样配置:
OrdererOrgs:
- Name: Orderer
Domain: example.com
Specs:
- Hostname: orderer
CommonName: myorderer.example.com
- PeerOrgs则定义了管理peer节点的组织,配置了Org1和Org2两个组织,每个组织2套证书,除Admin之外的普通User数量为1,EnableNodeOUs为true,允许节点out of service,用于区分clients, admins, peers,在msp目录会生成config.yaml。
采用了Template模板定义节点:- Count:节点总数
- Start:节点下标起始值,默认为0
- Hostname 全限定域名,默认命名格式为{{.Prefix}}{{.Index}}
- Prefix:默认为peer
- Index:取Start值,无配置从0开始自增
PeerOrgs:
- Name: Org1
Domain: org1.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1
- Name: Org2
Domain: org2.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1
3.2 generateChannelArtifacts 生成创世区块
generateChannelArtifacts使用工具configtxgen,生成创世区块的脚本为:configtxgen -profile SampleMultiNodeEtcdRaft -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
,SampleMultiNodeEtcdRaft 用于生成创始区块,支持etcdraft模式的共识。
raft共识的创世区块配置如下,里面包含所有的raft节点配置:
SampleMultiNodeEtcdRaft:
<<: *ChannelDefaults
Capabilities:
<<: *ChannelCapabilities
Orderer:
<<: *OrdererDefaults # 引用OrdererDefaults详细配置
OrdererType: etcdraft # 排序类型为etcdraft
EtcdRaft:
Consenters: # 系统channel中raft节点配置
- Host: orderer.example.com
Port: 7050
ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
# 此处省略了其他orderer节点
Addresses:
- orderer.example.com:7050
- orderer2.example.com:8050
- orderer3.example.com:9050
- orderer4.example.com:10050
- orderer5.example.com:11050
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Application:
<<: *ApplicationDefaults
Organizations:
- <<: *OrdererOrg
Consortiums:
SampleConsortium:
Organizations:
- *Org1
- *Org2
orderer详细配置及相关注释如下:
Orderer: &OrdererDefaults
OrdererType: etcdraft
BatchTimeout: 2s # 打包区块的超时时间
BatchSize: # 控制打包到区块的交易量
MaxMessageCount: 10 # 打包到一个区块中的最大消息数量
AbsoluteMaxBytes: 99 MB # 打包到一个区块中允许的绝对最大字节数
PreferredMaxBytes: 512 KB # 打包到一个区块中的首选最大字节数
Organizations: # 参与orderer的组织列表
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
BlockValidation: # 指定orderer的区块中必须包含哪些签名,以便peer节点进行验证
Type: ImplicitMeta
Rule: "ANY Writers"
3.3 generateChannelArtifacts 生成channe配置
生成用户channe配置交易的脚本为:configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
,TwoOrgsChannel 用于生成两个组织的channel。
用户channel的配置及相关注释如下:
TwoOrgsChannel:
Consortium: SampleConsortium # 联盟名称
<<: *ChannelDefaults # 引用ChannelDefaults详细配置
Application:
<<: *ApplicationDefaults # 引用ApplicationDefaults详细配置
Organizations: # channel组织定义
- *Org1
- *Org2
Capabilities:
<<: *ApplicationCapabilities
用户channel的详细配置主要是针对channel的权限策略:
Channel: &ChannelDefaults
Policies: # channel权限策略 <ALL|ANY|MAJORITY> <sub_policy>
# Who may invoke the 'Deliver' API
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
# Who may invoke the 'Broadcast' API
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
# By default, who may modify elements at this config level
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
Capabilities:
<<: *ChannelCapabilities
4. 节点启动分析
正如第2章节所分析的,节点容器启动脚本中的yaml文件默认是两个:docker-compose-cli.yaml、docker-compose-etcdraft2.yaml。
docker-compose-cli.yaml中将会启动6个容器,脚本中使用命令docker-compose -f docker-compose-cli.yaml up -d 2>&1
启动这些节点,包括:
- 第一个排序节点:orderer.example.com
- 两个组织的4个peer节点:
- peer0.org1.example.com
- peer1.org1.example.com
- peer0.org2.example.com
- peer1.org2.example.com
- fabric客户端:cli
docker-compose-etcdraft2.yaml中将会启动剩余的4个orderer容器,脚本中使用命令docker-compose -f docker-compose-etcdraft2.yaml up -d 2>&1
启动这些节点,包括:
- orderer2.example.com
- orderer3.example.com
- orderer4.example.com
- orderer5.example.com
4.1 第一个排序节点的启动
第一个排序节点的yaml配置如下:
orderer.example.com:
extends:
file: base/docker-compose-base.yaml
service: orderer.example.com
container_name: orderer.example.com
networks:
- byfn
其中引入了外部的yaml文件base/docker-compose-base.yaml;引入的orderer.example.com的相关配置如下:
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
其中引入了外部yaml文件peer-base.yaml,还定义了挂载目录、暴露的端口;外部yaml中的orderer-base服务如下:
orderer-base:
image: hyperledger/fabric-orderer:$IMAGE_TAG
environment:
- FABRIC_LOGGING_SPEC=INFO
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
- ORDERER_GENERAL_BOOTSTRAPMETHOD=file
- ORDERER_GENERAL_BOOTSTRAPFILE=/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_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
其中定义了镜像名称、环境变量配置、工作目录、启动命令,环境变量配置包括监听地址、证书地址等。
orderer启动后会建立一个raft集群。
使用命令docker logs -f orderer.example.com
可查看到第一个orderer启动的日志,可查看到主要过程为:
- 根据orderer1的配置初始化排序节点
- 创建本地账本目录
- 设置排序节点服务监听端口
- 根据创始区块文件初始化本地账本
- 启动fabric系统通道
- 启动raft服务
4.2 peer节点的启动
peer的yaml文件配置结构与orderer类似,不在赘述。
使用命令docker logs -f peer0.org1.example.com
可查看到其中一个peer的启动日志:
日志中会输出容器的基本信息,peer节点启动过程主要是:
- 启动peer grpc服务;
- 初始化gossip服务;
- 初始化本地账本;
- 安装系统链码,这里比起1.x,2.0多了一个系统链码_lifecycle,负责生命周期管理;
- 基于gossip对同组织节点进行交互。
4.3 剩余4个排序节点的启动
docker-compose-etcdraft2.yaml中将会启动剩余的4个orderer容器。脚本中使用命令docker-compose -f docker-compose-etcdraft2.yaml up -d 2>&1
启动这些节点。
查看一开始启动的第一个orderer的日志,可看到orderer.example.com以及成功连接其他raft节点,并且在raft 的term2,leader从orderer.example.com(0)变成orderer5.example.com(5)。
查看orderer5.example.com的日志,在term2 经过一轮投票后,orderer5获得5票回应成为了term2的raft leader。
Fabric网络已完全启动,docker ps
命令查看所有启动的节点:
感谢富强的博客:
https://blog.csdn.net/qq_28540443/article/details/104298137