Bootstrap

Fabric的数据持久化实现

参考文章

  1. 触不可及的深入解析Hyperledger Fabric搭建的全过程:
    https://ifican.top/2019/11/23/blog/fabric/%E6%B7%B1%E5%85%A5%E8%A7%A3%E6%9E%90Fabric%E6%90%AD%E5%BB%BA%E7%9A%84%E5%85%A8%E8%BF%87%E7%A8%8B/
  2. Hyperledger fabric : 单机多节点kafka模式的数据持久化:
    https://www.wandouip.com/t5i98262/
  3. willaty的博客园博文 fabric持久化
    https://www.cnblogs.com/willaty/p/10077531.html
  4. Hyperledger Fabric 1.0 实例简析 第一课 network_setup.sh分析
    https://blog.csdn.net/tiandiwuya/article/details/79471094

准备工作

按照触不可及的深入理解一篇,熟练通过改变环境变量手动搭建成功Fabric网络

解释

首先介绍四篇参考文章分别的作用。第一篇是具体操作命令,包括生成通道配置信息、创建通道等;第二篇是数据持久化的具体步骤;第三篇是实现持久化需要在docker-compose.yaml中添加的不同角色对应的具体参数;第四篇是解释第二篇中脚本文件具体干了什么。

根据第二篇文章的具体操作来实现持久化。其中generateArtifacts.sh和script.sh具体操作的内容可以通过第四篇文章来得到解释,并且根据触不可及一文中的操作命令可以手动实现。

实现过程

1. 正常配置区块链网络

首先正常启动区块链网络。

若generateArtifacts.sh没有或不可用,则手动搭建网络。这里引用触不可及中的前部分内容。

生成证书

#路径需要更改为自己的路径
cd ~/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network/  
#在这里可能会报错,通常是权限问题,可以添加sudo重新执行
cryptogen generate --config=./crypto-config.yaml
#执行完毕后,当前文件夹下会出现一个新的文件夹:crypto-config,在该文件夹下就是刚刚生成的证书.

生成创世区块

#执行命令生成创世区块 
configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
#如果没有channel-artifacts这个文件夹,则需要手动去创建

生成通道配置信息

#执行命令生成通道配置信息
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel

生成锚节点配置文件

#首先生成Org1的锚节点配置文件
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
#生成Org2的锚节点配置文件
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP

所有需要的配置文件全部建立完成,在channel-artifacts中应该有以下几个文件:

channel.tx  genesis.block  Org1MSPanchors.tx  Org2MSPanchors.tx

2. 更改docker-compose配置文件(暂时未配置couchdb)

在1.4.4版本的fabric-example的first-network中,可以看到docker-compose-cli.yaml下的配置继承了base目录下的docker-compose.yaml文件

extends:
  file:   base/docker-compose-base.yaml

在base目录下的docker-compose.yaml中,在volume的最后增加参数使得docker挂载到本地目录(本地目录必须创建,具体对应参考第三篇博客园的文章)

我的配置文件如下,仅供参考

# 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:8051
      - 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:8051
      - CORE_PEER_LISTENADDRESS=0.0.0.0:8051
      - CORE_PEER_CHAINCODEADDRESS=peer1.org1.example.com:8052
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:8052
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:8051
      - 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:
      - 8051:8051

  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:9051
      - CORE_PEER_LISTENADDRESS=0.0.0.0:9051
      - CORE_PEER_CHAINCODEADDRESS=peer0.org2.example.com:9052
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:9052
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:9051
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org2.example.com:10051
      - 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:
      - 9051:9051

  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:10051
      - CORE_PEER_LISTENADDRESS=0.0.0.0:10051
      - CORE_PEER_CHAINCODEADDRESS=peer1.org2.example.com:10052
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:10052
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.example.com:10051
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:9051
      - 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:
      - 10051:10051

3. 启动网络并验证持久化

继续按照第二篇文章中的步骤。

  1. 启动网络
sudo docker-compose -f docker-compose-cli.yaml up -d
  1. 进入cli容器
sudo docker exec -it cli bash
  1. 创建mychannel通道并加入,安装链码及实例化
# 此步骤也可按照深入理解一篇手动更改环境变量操作
./scripts/script.sh mychannel
  1. 执行invoke、query操作
# query
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
# invoke
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:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}'
  1. tree命令查看/var/hyperledger文件,确实有备份的容器数据
.
├── orderer
│   └── orderer
├── peer0
│   ├── org1
│   │   ├── chaincodes
│   │   │   └── mycc.1.0
│   │   ├── ledgersData
│   │   │   ├── bookkeeper
│   │   │   │   ├── 000002.log
│   │   │   │   ├── CURRENT
│   │   │   │   ├── CURRENT.bak
│   │   │   │   ├── LOCK
│   │   │   │   ├── LOG
│   │   │   │   └── MANIFEST-000003
│   │   │   ├── chains
│   │   │   │   ├── chains
│   │   │   │   │   └── mychannel
│   │   │   │   │       └── blockfile_000000
│   │   │   │   └── index
│   │   │   │       ├── 000002.ldb
│   │   │   │       ├── 000003.log
│   │   │   │       ├── CURRENT
│   │   │   │       ├── CURRENT.bak
│   │   │   │       ├── LOCK
│   │   │   │       ├── LOG
│   │   │   │       └── MANIFEST-000004
│   │   │   ├── configHistory
│   │   │   │   ├── 000002.log
│   │   │   │   ├── CURRENT
│   │   │   │   ├── CURRENT.bak
│   │   │   │   ├── LOCK
│   │   │   │   ├── LOG
│   │   │   │   └── MANIFEST-000003
│   │   │   ├── fileLock
│   │   │   │   ├── 000002.log
│   │   │   │   ├── CURRENT
│   │   │   │   ├── CURRENT.bak
│   │   │   │   ├── LOCK
│   │   │   │   ├── LOG
│   │   │   │   └── MANIFEST-000003
│   │   │   ├── historyLeveldb
│   │   │   │   ├── 000002.ldb
│   │   │   │   ├── 000003.log
│   │   │   │   ├── CURRENT
│   │   │   │   ├── CURRENT.bak
│   │   │   │   ├── LOCK
│   │   │   │   ├── LOG
│   │   │   │   └── MANIFEST-000004
│   │   │   ├── ledgerProvider
│   │   │   │   ├── 000002.ldb
│   │   │   │   ├── 000003.log
│   │   │   │   ├── CURRENT
│   │   │   │   ├── CURRENT.bak
│   │   │   │   ├── LOCK
│   │   │   │   ├── LOG
│   │   │   │   └── MANIFEST-000004
│   │   │   ├── pvtdataStore
│   │   │   │   ├── 000002.ldb
│   │   │   │   ├── 000003.log
│   │   │   │   ├── CURRENT
│   │   │   │   ├── CURRENT.bak
│   │   │   │   ├── LOCK
│   │   │   │   ├── LOG
│   │   │   │   └── MANIFEST-000004
│   │   │   └── stateLeveldb
│   │   │       ├── 000002.ldb
│   │   │       ├── 000003.log
│   │   │       ├── CURRENT
│   │   │       ├── CURRENT.bak
│   │   │       ├── LOCK
│   │   │       ├── LOG
│   │   │       └── MANIFEST-000004
│   │   └── transientStore
│   │       ├── 000002.log
│   │       ├── CURRENT
│   │       ├── CURRENT.bak
│   │       ├── LOCK
│   │       ├── LOG
│   │       └── MANIFEST-000003
│   └── org2
│       ├── chaincodes
│       │   └── mycc.1.0
│       ├── ledgersData
│       │   ├── bookkeeper
│       │   │   ├── 000002.log
│       │   │   ├── CURRENT
│       │   │   ├── CURRENT.bak
│       │   │   ├── LOCK
│       │   │   ├── LOG
│       │   │   └── MANIFEST-000003
│       │   ├── chains
│       │   │   ├── chains
│       │   │   │   └── mychannel
│       │   │   │       └── blockfile_000000
│       │   │   └── index
│       │   │       ├── 000002.ldb
│       │   │       ├── 000003.log
│       │   │       ├── CURRENT
│       │   │       ├── CURRENT.bak
│       │   │       ├── LOCK
│       │   │       ├── LOG
│       │   │       └── MANIFEST-000004
│       │   ├── configHistory
│       │   │   ├── 000002.log
│       │   │   ├── CURRENT
│       │   │   ├── CURRENT.bak
│       │   │   ├── LOCK
│       │   │   ├── LOG
│       │   │   └── MANIFEST-000003
│       │   ├── fileLock
│       │   │   ├── 000002.log
│       │   │   ├── CURRENT
│       │   │   ├── CURRENT.bak
│       │   │   ├── LOCK
│       │   │   ├── LOG
│       │   │   └── MANIFEST-000003
│       │   ├── historyLeveldb
│       │   │   ├── 000002.ldb
│       │   │   ├── 000003.log
│       │   │   ├── CURRENT
│       │   │   ├── CURRENT.bak
│       │   │   ├── LOCK
│       │   │   ├── LOG
│       │   │   └── MANIFEST-000004
│       │   ├── ledgerProvider
│       │   │   ├── 000002.ldb
│       │   │   ├── 000003.log
│       │   │   ├── CURRENT
│       │   │   ├── CURRENT.bak
│       │   │   ├── LOCK
│       │   │   ├── LOG
│       │   │   └── MANIFEST-000004
│       │   ├── pvtdataStore
│       │   │   ├── 000002.ldb
│       │   │   ├── 000003.log
│       │   │   ├── CURRENT
│       │   │   ├── CURRENT.bak
│       │   │   ├── LOCK
│       │   │   ├── LOG
│       │   │   └── MANIFEST-000004
│       │   └── stateLeveldb
│       │       ├── 000002.ldb
│       │       ├── 000003.log
│       │       ├── CURRENT
│       │       ├── CURRENT.bak
│       │       ├── LOCK
│       │       ├── LOG
│       │       └── MANIFEST-000004
│       └── transientStore
│           ├── 000002.log
│           ├── CURRENT
│           ├── CURRENT.bak
│           ├── LOCK
│           ├── LOG
│           └── MANIFEST-000003
└── peer1
    ├── org1
    │   ├── chaincodes
    │   ├── ledgersData
    │   │   ├── bookkeeper
    │   │   │   ├── 000002.log
    │   │   │   ├── CURRENT
    │   │   │   ├── CURRENT.bak
    │   │   │   ├── LOCK
    │   │   │   ├── LOG
    │   │   │   └── MANIFEST-000003
    │   │   ├── chains
    │   │   │   ├── chains
    │   │   │   │   └── mychannel
    │   │   │   │       └── blockfile_000000
    │   │   │   └── index
    │   │   │       ├── 000002.ldb
    │   │   │       ├── 000003.log
    │   │   │       ├── CURRENT
    │   │   │       ├── CURRENT.bak
    │   │   │       ├── LOCK
    │   │   │       ├── LOG
    │   │   │       └── MANIFEST-000004
    │   │   ├── configHistory
    │   │   │   ├── 000002.log
    │   │   │   ├── CURRENT
    │   │   │   ├── CURRENT.bak
    │   │   │   ├── LOCK
    │   │   │   ├── LOG
    │   │   │   └── MANIFEST-000003
    │   │   ├── fileLock
    │   │   │   ├── 000002.log
    │   │   │   ├── CURRENT
    │   │   │   ├── CURRENT.bak
    │   │   │   ├── LOCK
    │   │   │   ├── LOG
    │   │   │   └── MANIFEST-000003
    │   │   ├── historyLeveldb
    │   │   │   ├── 000002.ldb
    │   │   │   ├── 000003.log
    │   │   │   ├── CURRENT
    │   │   │   ├── CURRENT.bak
    │   │   │   ├── LOCK
    │   │   │   ├── LOG
    │   │   │   └── MANIFEST-000004
    │   │   ├── ledgerProvider
    │   │   │   ├── 000002.ldb
    │   │   │   ├── 000003.log
    │   │   │   ├── CURRENT
    │   │   │   ├── CURRENT.bak
    │   │   │   ├── LOCK
    │   │   │   ├── LOG
    │   │   │   └── MANIFEST-000004
    │   │   ├── pvtdataStore
    │   │   │   ├── 000002.ldb
    │   │   │   ├── 000003.log
    │   │   │   ├── CURRENT
    │   │   │   ├── CURRENT.bak
    │   │   │   ├── LOCK
    │   │   │   ├── LOG
    │   │   │   └── MANIFEST-000004
    │   │   └── stateLeveldb
    │   │       ├── 000002.ldb
    │   │       ├── 000003.log
    │   │       ├── CURRENT
    │   │       ├── CURRENT.bak
    │   │       ├── LOCK
    │   │       ├── LOG
    │   │       └── MANIFEST-000004
    │   └── transientStore
    │       ├── 000002.log
    │       ├── CURRENT
    │       ├── CURRENT.bak
    │       ├── LOCK
    │       ├── LOG
    │       └── MANIFEST-000003
    └── org2
        ├── chaincodes
        │   └── mycc.1.0
        ├── ledgersData
        │   ├── bookkeeper
        │   │   ├── 000002.log
        │   │   ├── CURRENT
        │   │   ├── CURRENT.bak
        │   │   ├── LOCK
        │   │   ├── LOG
        │   │   └── MANIFEST-000003
        │   ├── chains
        │   │   ├── chains
        │   │   │   └── mychannel
        │   │   │       └── blockfile_000000
        │   │   └── index
        │   │       ├── 000002.ldb
        │   │       ├── 000003.log
        │   │       ├── CURRENT
        │   │       ├── CURRENT.bak
        │   │       ├── LOCK
        │   │       ├── LOG
        │   │       └── MANIFEST-000004
        │   ├── configHistory
        │   │   ├── 000002.log
        │   │   ├── CURRENT
        │   │   ├── CURRENT.bak
        │   │   ├── LOCK
        │   │   ├── LOG
        │   │   └── MANIFEST-000003
        │   ├── fileLock
        │   │   ├── 000002.log
        │   │   ├── CURRENT
        │   │   ├── CURRENT.bak
        │   │   ├── LOCK
        │   │   ├── LOG
        │   │   └── MANIFEST-000003
        │   ├── historyLeveldb
        │   │   ├── 000002.ldb
        │   │   ├── 000003.log
        │   │   ├── CURRENT
        │   │   ├── CURRENT.bak
        │   │   ├── LOCK
        │   │   ├── LOG
        │   │   └── MANIFEST-000004
        │   ├── ledgerProvider
        │   │   ├── 000002.ldb
        │   │   ├── 000003.log
        │   │   ├── CURRENT
        │   │   ├── CURRENT.bak
        │   │   ├── LOCK
        │   │   ├── LOG
        │   │   └── MANIFEST-000004
        │   ├── pvtdataStore
        │   │   ├── 000002.ldb
        │   │   ├── 000003.log
        │   │   ├── CURRENT
        │   │   ├── CURRENT.bak
        │   │   ├── LOCK
        │   │   ├── LOG
        │   │   └── MANIFEST-000004
        │   └── stateLeveldb
        │       ├── 000002.ldb
        │       ├── 000003.log
        │       ├── CURRENT
        │       ├── CURRENT.bak
        │       ├── LOCK
        │       ├── LOG
        │       └── MANIFEST-000004
        └── transientStore
            ├── 000002.log
            ├── CURRENT
            ├── CURRENT.bak
            ├── LOCK
            ├── LOG
            └── MANIFEST-000003
  1. 关闭docker容器
sudo docker rm -f $(sudo docker ps -aq)
# 注意: 不需要把channel-artifacts和crypto-config两个文件也删掉
  1. 重启docker后进入容器,直接进行invoke,query操作,发现可行,并且仍是继续上次的数据。也就是跳过了链码安装、部署、实例化等等操作,即测试完成。
;