
1. 环境评估与版本选型1.1 为什么要选Fabric 1.4作为入门版本先说说版本这个问题。Hyperledger Fabric目前已经有2.x系列了但1.4作为LTS版本稳定性和社区资料的丰富程度都是最好的。很多生产环境和教学资源都停留在1.4如果你是想快速搭建一条可用链来验证业务逻辑1.4是目前最不容易“劝退”的版本。我当初踩过最大的坑就是直接拿最新版教程去跑老版本结果命令不兼容、配置文件格式对不上最后只能推倒重来。Fabric 1.4的核心组件包括peer节点、orderer节点、fabric-ca这三个角色的启动方式和配置文件模板都和2.x有明显差异。整个搭建过程需要准备的东西可以概括为五部分基础操作系统环境Docker及Docker Compose容器运行环境Go语言编译环境主要用于链码开发调试Fabric源码与二进制文件组织证书、通道配置等材料这套环境准备下来一台4核8G的普通主机完全够用我自己测试时用的是某云服务器跑四个Peer加一个Orderer节点没什么压力。1.2 操作系统与软件环境的具体版本要求Fabric 1.4官方推荐的宿主系统是Ubuntu 16.04或18.04。这里特别注意一下操作系统建议装英文环境路径中尽量不要出现中文和空格。某次我在一台中文环境下跑脚本各种奇奇怪怪的编码问题花了半天才排查干净。各软件版本有一个建议组合放在下面表格里你可以直接照着配软件名称推荐版本说明Ubuntu16.04 / 18.04兼容性最好官方CI验证过的版本Docker17.06.2-ce及以上不能低于这个版本否则Fabric镜像内部指令可能不支持Docker Compose1.14.0及以上用于编排多容器启动Go1.11.x过高版本可能导致某些依赖编译出错Node.js8.9及以上如果要用Node.js链码才需要纯Go链码可不装Python2.7Fabric脚本依赖Ubuntu自带这里的版本组合是官方在持续集成环境中验证过的我自己试过Go 1.15、Docker 19.03Fabric 1.4也能跑但总有点“能用但不安心”的感觉。如果希望后续跟着教程一步步不出岔子建议严格按官方推荐版本来。1.3 环境准备前的依赖关系梳理Fabric 1.4整个启动链路里Docker是核心中的核心。Fabric节点本身不用你在宿主机上装什么复杂的运行库它是以容器方式运行的宿主机只需要能跑Docker、能拉取镜像、能编排容器即可。所以环境准备的核心逻辑就三个词装Docker、装Compose、装Go。Go的用途主要是编译链码。在Fabric 1.4中链码可以有两种运行方式一种是在Docker容器内编译运行另一种是外部构建。初期建议用默认的容器内方式省去很多环境变量配置。但即使你不用Go写链码宿主机也需要有Go环境因为测试链码时Fabric会调用Go编译器把链码源码打成可执行文件。我遇到过这样一个小问题Go装了新版导致链码实例化报错报错信息是“go: unknown subcommand”其实就是Go版本太新一些旧接口被移除了。把Go降到1.11.x之后问题立刻消失。2. Fabric组件获取与前期准备2.1 通过脚本快速拉取源码、二进制与镜像Fabric官方提供了一个一键脚本能把源码、二进制、Docker镜像一次性拉下来。脚本路径是scripts/bootstrap.sh。我在初期搭建时就是靠这个脚本省了大量手动拉取的时间。脚本的核心动作大致是这样的curl -sSLO https://raw.githubusercontent.com/hyperledger/fabric/v1.4.0/scripts/bootstrap.sh chmod x bootstrap.sh ./bootstrap.sh 1.4.0 1.4.0 1.4.0三个参数分别对应Fabric版本、Fabric-ca版本、第三方镜像版本。脚本会先克隆Fabric源码到本地然后下载对应的二进制工具cryptogen、configtxgen、peer、orderer等最后拉取docker镜像。这套流程跑完你会得到一个名为fabric-samples的目录里面有bin、config、chaincode等子目录。后续多节点配置都要基于这个目录下的文件进行修改。2.2 手动下载的备用方案脚本虽然方便但网络条件不好时容易卡在git clone那一步。我建议在特殊情况下手动操作思路是一样的先建好工作目录然后用git克隆mkdir -p /opt/fabric cd /opt/fabric git clone https://github.com/hyperledger/fabric-samples.git cd fabric-samples git checkout v1.4.0二进制工具则需要在GitHub的release页面手动下载对应压缩包解压后把bin目录下的可执行文件放到/usr/local/bin或配置到PATH环境变量中。镜像方面依然可以复用bootstrap脚本后半段的docker pull命令或者直接用下面的命令把常用镜像全部拉取docker pull hyperledger/fabric-peer:1.4.0 docker pull hyperledger/fabric-orderer:1.4.0 docker pull hyperledger/fabric-ca:1.4.0 docker pull hyperledger/fabric-ccenv:1.4.0 docker pull hyperledger/fabric-tools:1.4.0镜像版本和二进制版本必须严格对应否则可能出现“peer二进制与网络不兼容”的错误。2.3 工作目录结构说明Fabric 1.4的网络配置主要集中在fabric-samples目录下的first-network子目录中。这个目录包含了完整的示例网络两个组织、一个Orderer、四个Peer节点。初期做多节点配置时最推荐的方案就是在这个示例上做改造而不是从头写配置文件。first-network目录下几个核心文件需要先眼熟一下crypto-config.yaml定义组织结构和证书生成规则configtx.yaml定义通道配置、创世区块、锚节点更新配置docker-compose-cli.yaml定义容器编排scripts/script.sh自动化创建通道、加入通道、安装链码理解了这几个文件就等于握住了Fabric网络配置的命门。后面所有定制化多节点方案都是在这几个文件上做文章。3. 多节点网络拓扑与配置方案3.1 单机多节点的最简拓扑设计初期学习阶段不需要追求复杂的多机分布单机多节点是性价比最高的方式。用Docker在同一个宿主机上启动多个Peer容器每个Peer容器通过端口映射对外提供服务这就是“单机多节点”的核心思路。我推荐的最小可行拓扑是一个Orderer节点默认端口7050两个组织Org1、Org2每个组织各一个Peer节点端口7051和8051这个拓扑覆盖了多组织、多节点的核心场景又不会复杂到难以排查问题。如果你要练习更深度的配置可以扩展到每个组织两个Peer节点再引入锚节点概念。上面说的这种扩展方式是在docker-compose-cli.yaml里增加peer的容器定义同时修改crypto-config.yaml把每个组织的Peer数量从1改成2重新生成证书即可。3.2 多机多节点的网络规划思路当你从单机切到多机时最先要处理的是容器端口映射和跨主机通信问题。Fabric 1.4的节点间通信默认走gRPC如果你让Peer和Orderer分布在不同机器上必须确保以下两个条件成立第一所有节点的主机名或IP能互相访问不能有防火墙拦截关键端口。第二在core.yaml或环境变量中正确配置CORE_PEER_ADDRESS和CORE_PEER_LISTENADDRESS让节点知道自己的对外地址。多机部署时还涉及证书分发。每个节点的MSP目录需要在启动前就准备好最稳妥的做法是在一台机器上生成全部证书然后分发到各节点对应路径。我见过有人在每台机器上单独生成证书结果因为各机器的crypto-config.yaml定义不一致导致节点之间无法互相验证身份。顺带说一个实用的网络配置技巧在多机环境下建议为每台机器设置固定IP并在/etc/hosts里互相绑定主机名。Fabric 1.4的证书中会记录主机名如果证书中的域名解析不到对应IP后续节点通讯就会报“unable to connect”的错误。3.3 证书生成规则与组织身份配置先来看crypto-config.yaml这个文件决定了网络中有哪些组织、哪些节点以及每个节点的身份证书。Fabric的证书机制你可以理解为给每个节点和组织发一张“数字身份证”所有节点在通讯前都要互相验证身份。一个典型的配置模板如下OrdererOrgs: - Name: Orderer Domain: example.com Specs: - Hostname: orderer 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配置中的Count表示这个组织的Peer节点数量。如果需要添加第三个组织直接按照同样的格式追加一个PeerOrgs条目。生成证书的命令是cd fabric-samples/first-network cryptogen generate --config./crypto-config.yaml执行完成后会生成一个crypto-config目录里面按组织和节点层级存放各种证书和私钥。这个目录在启动网络前会被挂载到容器内节点启动时自动加载。3.4 通道配置与创世区块参数解析configtx.yaml是另一个重头文件。它负责生成Orderer的创世区块、通道配置交易和锚节点更新交易。初次接触Fabric的人很容易把“创世区块”和“通道”搞混简单区分一下创世区块是Orderer服务的初始区块里面定义了整个联盟链网络有哪些组织、使用什么共识机制。通道则是在创世区块基础上创建的独立子链业务数据只在通道内传播与通道外的节点无关。configtx.yaml最核心的部分是Profiles段它定义了两类模板Profiles: TwoOrgsOrdererGenesis: Capabilities: : *ChannelCapabilities Orderer: : *OrdererDefaults Organizations: - *OrdererOrg Consensus: Type: solo Consortiums: SampleConsortium: Organizations: - *Org1 - *Org2 TwoOrgsChannel: Consortium: SampleConsortium Application: : *ApplicationDefaults Organizations: - *Org1 - *Org2TwoOrgsOrdererGenesis用来生成创世区块TwoOrgsChannel用来生成通道交易文件。初学者不需要改动太多内容默认模板已经能支撑起一个多组织网络。4. 网络启动与通道创建实操4.1 生成创世区块与通道配置文件在启动了所有节点之前需要先生成三个关键文件创世区块、通道配置交易、锚节点更新交易。这些文件通过configtxgen工具生成。export FABRIC_CFG_PATH$PWD configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel configtxgen -profile TwoOrgsChannel -outputAnchorPeerUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP configtxgen -profile TwoOrgsChannel -outputAnchorPeerUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP注意命令执行前必须把FABRIC_CFG_PATH指向包含configtx.yaml的目录否则工具找不到配置文件。这里的channelID需要记好后续所有创建通道、加入通道的命令都必须一致。我这里需要补充一个经验初次操作时如果channel-artifacts目录不存在要先创建。另外configtxgen默认会把生成的配置文件名打印在日志里建议生成后立刻检查文件大小一般情况下创世区块应该在几KB到几十KB之间如果文件太小可能是配置有误。4.2 通过Docker Compose启动各节点容器启动容器是整个配置过程中比较直观的一步。在first-network目录下执行docker-compose -f docker-compose-cli.yaml up -d这个命令会按照编排文件依次启动Orderer、Peer以及CLI容器。CLI容器是一个特殊的客户端容器用于执行创建通道、安装链码等管理命令。启动后建议先检查一下容器状态docker ps正常情况下你会看到一个Orderer容器名称类似orderer.example.com两个或多个Peer容器名称类似peer0.org1.example.com、peer0.org2.example.com一个CLI容器名称类似cli如果某个容器启动后立即退出先查看对应日志docker logs 容器名称最常见的启动失败原因包括证书目录未挂载正确、创世区块路径配置错误、端口冲突。端口冲突很典型比如本机已经占了7051端口Peer容器就会启动失败。4.3 进入CLI容器创建并加入通道节点启动完成之后真正的通道创建工作是在CLI容器里进行的。CLI容器挂载了所有Peer的MSP目录所以可以代表不同组织执行操作。先进入CLI容器docker exec -it cli bash在容器内需要先设置环境变量指定你要操作的组织和Peer。以Org1为例export CORE_PEER_MSPCONFIGPATH/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Adminorg1.example.com/msp export CORE_PEER_ADDRESSpeer0.org1.example.com:7051 export CORE_PEER_LOCALMSPIDOrg1MSP然后创建通道peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx执行成功后会在容器内生成一个mychannel.block文件这就是通道的创世块。之后另一个组织要加入通道需要先把Peer的环境变量切换到对应组织然后执行peer channel join -b mychannel.block每个Peer节点都要执行一次join操作也就是说如果你有四个Peer这个命令要执行四次每次切换不同的CORE_PEER_ADDRESS和CORE_PEER_MSPCONFIGPATH。4.4 锚节点更新的作用与实际操作通道配置中有一个容易忽视的细节锚节点。锚节点的作用是让不同组织之间的Peer可以通过它发现彼此。在跨组织链码调用时如果没有设置锚节点就可能出现Peer之间找不到对方的情况。更新锚节点的命令如下peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org2MSPanchors.tx这两条命令必须在对应组织的环境下执行。也就是说第一次执行时环境变量指向Org1第二次切换到Org2。我建议在配置多组织网络时把锚节点更新作为通道创建的固定步骤别省略。5. 链码部署与网络功能验证5.1 链码安装与实例化的核心逻辑通道创建好了Peer也加入了但一个区块链网络真正能跑业务还要安装链码。链码就是运行在Peer上的智能合约Fabric 1.4中链码的生命周期分两步安装和实例化。安装是把链码源码编译后的代码包放到Peer的指定目录。这一步在每个需要运行链码的Peer上都要单独执行。如果只有Org1的Peer安装了链码Org2的Peer上没有那么Org2就不能对这笔链码发起交易。以first-network自带的示例链码为例peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/执行完成后Peer会返回一个链码包标识和哈希值。实例化则是初始化链码并定义链上的初始状态只需要在同一个通道内的某一个Peer上执行即可peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n mycc -v 1.0 -c {Args:[init,a,100,b,200]} -P AND (Org1MSP.peer,Org2MSP.peer)这里的-P参数定义了背书策略指定的意思是交易必须由Org1和Org2的Peer共同背书才能生效。在实际项目中背书策略要根据业务需求灵活调整。这里有个非常容易踩的坑实例化链码时如果其他Peer还没有安装链码实例化不论成功与否其他Peer的日志里都会报错。这不是网络问题只需要继续把链码安装到其他Peer再调用一次就行了。5.2 链码调用与查询验证链码实例化成功之后可以做一次简单的转账和查询操作来验证网络是否通畅。查询操作peer chaincode query -C mychannel -n mycc -c {Args:[query,a]}预期返回值为100这是实例化时给a账户的初始余额。转账操作peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n mycc -c {Args:[invoke,a,b,10]}转账成功后再次查询a账户如果返回90说明链码逻辑执行成功区块也已经生成。到这一步一个完整的Fabric 1.4多节点网络就算是真正跑通了。5.3 数据持久化与容器重启策略Docker容器本身是无状态的容器一停节点内存里暂存的数据就会丢失。但Fabric网络的数据在正常情况下是持久化到宿主机的默认配置中Peer和Orderer会把账本数据写到容器的/var/hyperledger/production目录也就是映射到宿主机的对应路径。也就是说如果意外重启了Docker容器只要映射的宿主机目录没有被删除账本数据就不会丢。我在实际运行中遇到过一个情况某次宿主机磁盘空间满了Peer容器不断重启账本数据差点损坏。后来加了一条定时清理Docker悬空镜像的脚本把风险降了下来。如果你想彻底重置网络重新开始需要清理的数据范围包括docker stop $(docker ps -aq) docker rm $(docker ps -aq) docker volume prune -f rm -rf channel-artifacts crypto-config然后再从证书生成开始一步步重建。6. 高频故障排查与配置心得6.1 节点间通信失败的典型排查路径多节点网络最常见的问题是节点之间互相通讯失败。这类问题可以从三个方向排查证书、网络、配置。证书问题通常表现为类似这样的日志[grpc] Failed to dial: connection error: desc transport: authentication handshake failed这种情况下第一优先检查证书是否放到了正确路径是否使用了对应组织的管理员证书。我经常看到有人把Org1的证书当成Org2的证书发给节点结果通讯握手阶段就出错。网络问题通常表现为超时或连接拒绝。可以用简单的ping和telnet来验证节点之间的连通性telnet orderer的IP 7050如果端口不通先检查防火墙再看Docker端口映射是否配置正确。配置问题则主要集中在CORE_PEER_ADDRESS、CORE_PEER_LOCALMSPID和CORE_PEER_MSPCONFIGPATH这三个环境变量是否对应当前操作的组织。6.2 链码实例化卡住或失败的几个怪状链码实例化是个低概率一次通过的操作。你可能会遇到实例化命令执行后一直挂在“waiting for chaincode to start”的状态然后超时失败。这个问题的根源多半是Peer容器拉取链码镜像失败。1.4版本中Peer会基于fabric-ccenv镜像启动一个临时的链码容器。宿主机的Docker如果无法从仓库拉取对应镜像或者链码编译过程中发生依赖下载超时实例化就会失败。解决办法是提前手动把链码依赖的基础镜像拉下来确保本机已经缓存了以下镜像docker pull hyperledger/fabric-ccenv:1.4.0 docker pull hyperledger/fabric-baseos:amd64-0.4.15另一个很隐蔽的问题是链码源码路径。实例化时-p参数指向的是链码在CLI容器内的路径很多人直接写宿主机路径导致Peer找不到源码编译失败。如果你用的是first-network默认配置CLI容器内链码路径通常是github.com/chaincode/chaincode_example02/go/。6.3 常用运维命令汇总与自查脚本日常维护和问题排查经常要敲重复命令下面这些可以放在你的笔记里备用。场景命令查看所有容器状态docker ps -a查看某个容器日志docker logs 容器名进入CLI容器docker exec -it cli bash查看Peer所加入的通道peer channel list查看通道内的Peer节点peer channel getinfo -c mychannel查看已安装链码peer chaincode list --installed查看已实例化链码peer chaincode list --instantiated -C mychannel重置整个网络见前面清理数据一节把这些命令整理成一个shell脚本每次出问题先跑一遍能省下不少重复劳动。6.4 基于完整落地过程的几点总结性体会整套Fabric 1.4环境搭建和多节点配置走下来我个人最大的感受是这个系统的门槛不在于理解区块链概念而在于把各种配置文件之间的依赖关系理顺。证书、创世区块、通道配置、节点地址任何一个环节错位表现出的症状都是节点起不来或通讯失败不熟悉的人容易在错误方向上反复排查。如果你按本文流程走从环境准备到链码验证一次跑通的可能性很高。如果中途卡在任何一步优先检查版本、路径和证书这三类基础问题绝大多数故障都能从这里找到原因。最后分享一个小技巧在修改configtx.yaml或crypto-config.yaml前先把原始文件备份一份。Fabric的配置文件解析逻辑比较严格一个多出来的空格都可能引发解析失败。有了备份你就可以放胆尝试各种自定义配置了。