zoukankan      html  css  js  c++  java
  • 在HyperLedger Fabric中启用CouchDB作为State Database

    回顾一下我之前的一篇博客,在Fabric 1.0中,我们存在3种类型的数据存储,一种是基于文件系统的区块链数据,这个跟比特币很像,比特币也是文件形式存储的。Fabric1.0中的区块链存储了Transaction订单读写集。而读写集到底是读什么?写什么?其实就是我们的State Database,也叫做World State,里面以键值对的方式存储了我们在ChainCode中操作的业务数据。另外还有就是对历史数据和区块链索引的数据库。

    区块链是文件系统,这个目前不支持更改,历史数据和区块链的索引是LevelDB,这个也不能更改。而对于State Database,由于和业务相关,所以提供了替换数据库,目前支持默认的LevelDB和用户可选择的CouchDB。这里要说到2点,一个是在0.6的时候其实用的RockDB,但是由于License的考虑,所以在1.0改成了LevelDB。另外就是CouchDB也不一定是最优的,很多人还考虑到MongoDB或者MySQL等,但是由于现在Fabric那边开发资源有限,所以在1.0还不会做,以后可能会实现。

    CouchDB安装

    下面我们来说一说这个CouchDB。

    CouchDB是一个完全局域RESTful API的键值数据库,也就是说我们不需要任何客户端,只需要通过HTTP请求就可以操作数据库了。LevelDB是Peer的本地数据库,那么肯定是和Peer一对一的关系,那么CouchDB是个网络数据库,应该和Peer是什么样一个关系呢?在生产环境中,我们会为每个组织部署节点,而且为了高可用,可能会在一个组织中部署多个Peer。同样我们在一个组织中也部署多个CouchDB,每个Peer对应一个CouchDB。

    HyperLedger在Docker Hub上也发布了CouchDB的镜像,为了能够深入研究CouchDB和Fabric的集成,我们就采用官方发布的CouchDB来做。

    docker pull klaemo/couchdb

    【注意,如果我们是docker pull couchdb,那么只能获得1.6版本的CouchDB,而要获得最新的2.0版,就需要用上面这个镜像。】

    可以获得官方的CouchDB镜像。CouchDB在启动的时候需要指定一个本地文件夹映射成CouchDB的数据存储文件夹,所以我们可以在当前用户的目录下创建一个文件夹用于存放数据。

    mkdir couchdb

    下载完成后,我们只需要执行以下命令即可启用一个CouchDB的实例:

    docker run -p 5984:5984 -d --name my-couchdb -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password -v ~/couchdb:/opt/couchdb/data klaemo/couchdb
    启动后我们打开浏览器,访问Linux的IP的5984端口的URL,比如我的Linux是192.168.100.129,那么URL是:
    http://192.168.100.129:5984/_utils
    这个时候我们就可以看到CouchDB的Web管理界面了。输入用户名admin密码password即可进入。
    image
    现在是一个空数据库,我们将CouchDB和Peer结合起来后再看会是什么样的效果。

    配置CouchDB+Fabric环境

    先删除刚才创建的CouchDB容器:
    docker rm -f my-couchdb
    首先我们是4个Peer+1Orderer的模式,所以我们先创建4个CouchDB数据库:
    cd ~ 
    mkdir couchdb0 
    mkdir couchdb1 
    mkdir couchdb2 
    mkdir couchdb3 
    docker run -p 5984:5984 -d --name couchdb0 -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password -v ~/couchdb0:/opt/couchdb/data klaemo/couchdb 
    docker run -p 6984:5984 -d --name couchdb1 -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password -v ~/couchdb1:/opt/couchdb/data klaemo/couchdb 
    docker run -p 7984:5984 -d --name couchdb2 -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password -v ~/couchdb2:/opt/couchdb/data klaemo/couchdb 
    docker run -p 8984:5984 -d --name couchdb3 -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password -v ~/couchdb3:/opt/couchdb/data klaemo/couchdb

    然后我们需要启动Fabric了。Fabric的准备环境,可以参见我们这篇博客:http://www.cnblogs.com/studyzy/p/6973334.html

    官方已经提供了多个Docker-compose文件,如果我们使用的是./network_setup.sh up命令,那么启用的就是docker-compose-cli.yaml这个文件。如果要基于这个yaml文件启用CouchDB的Peer,则打开该文件,并编辑其中的Peer节点,改为如下的形式:

    peer0.org1.example.com:
      container_name: peer0.org1.example.com
      environment:
        - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
        - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=192.168.100.129:5984
        - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=admin
        - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=password

      extends:
        file:  base/docker-compose-base.yaml
        service: peer0.org1.example.com

    这里的192.168.100.129:5984是我映射CouchDB后的Linux的IP地址和IP。然后是设置用户名和密码。把4个Peer的配置都改好后,保存,我们试着启用Fabric:

    ./network_setup.sh up

    等Fabric启动完成并运行了ChainCode测试后,我们刷新http://192.168.100.129:5984/_utils ,可以看到以Channel名字创建的Database,另外还有几个是系统数据库。

    image
    点进mychannel数据库,我们可以看到其中的数据内容。点击“Mango Query”可以编写查询,默认提供的查询可以点击Run Query按钮查询所有的数据结果:
    image

    CouchDB的直接查询

    接下来我们使用Linux的curl来查询CouchDB数据库。
    比如我们要看看mychannel数据库下有哪些数据:
    curl http://192.168.100.129:5984/mychannel/_all_docs
    可以看到我运行了一些ChainCode后的State DATABASE结果:

    {"total_rows":7,"offset":0,"rows":[
    {"id":"devinccu0000a","key":"devinccu0000a","value":{"rev":"2-a979bf6c2716ecae6d106999f833a59c"}},
    {"id":"devinccu0000b","key":"devinccu0000b","value":{"rev":"2-ad1c549305fd277097180405f96bdcd8"}},
    {"id":"lsccu0000devincc","key":"lsccu0000devincc","value":{"rev":"1-05d2cd0b344c4dd8a8d1a3ffd7332544"}},
    {"id":"lsccu0000mycc","key":"lsccu0000mycc","value":{"rev":"1-2cba0344b1610b9d9254bbafbda5e9b1"}},
    {"id":"myccu0000a","key":"myccu0000a","value":{"rev":"2-588a45b289359afa9dc6e5e7866eaf97"}},
    {"id":"myccu0000b","key":"myccu0000b","value":{"rev":"2-54e6639a858b0f91298c9a354484513a"}},
    {"id":"statedb_savepoint","key":"statedb_savepoint","value":{"rev":"10-6ccde2a55c71d7d6a70d9333d119fc8e"}}
    ]}

    如果我们要查询其中的一条数据,只需要用/ChannelId/id来查询,比如查询:statedb_savepoint

    curl http://192.168.100.129:5984/mychannel/statedb_savepoint

    返回的结果:
    {"_id":"statedb_savepoint","_rev":"10-6ccde2a55c71d7d6a70d9333d119fc8e","BlockNum":4,"TxNum":0,"UpdateSeq":"19-g1AAAAEzeJzLYWBg4MhgTmHgzcvPy09JdcjLz8gvLskBCjMlMiTJ____PyuRAYeCJAUgmWQPVsOCS40DSE08WA0jLjUJIDX1eO3KYwGSDA1ACqhsPiF1CyDq9mclsuJVdwCi7j4h8x5A1AHdx5kFAI6sYwk"}

    麻烦的是业务数据是“ChainCodeNameu0000数据”这样的格式的ID,而如果我们要通过这个ID查询,那么就根本找不到啊!

    curl http://192.168.100.129:5984/mychannel/myccu0000a
    {"error":"not_found","reason":"missing"}

    正确的做法是把u0000替换为%00,也就是说我们的查询应该是:

    curl http://192.168.100.129:5984/mychannel/mycc%00a

    正确返回结果:
    {"_id":"myccu0000a","_rev":"2-588a45b289359afa9dc6e5e7866eaf97","chaincodeid":"mycc","version":"4:0","_attachments":{"valueBytes":{"content_type":"application/octet-stream","revpos":2,"digest":"md5-hhOYXsSeuPdXrmQ56Hm7Kg==","length":2,"stub":true}}}

    Fabric可能会遇到的问题

    虽然区块链是一个只能插入和查询的数据库,但是我们的业务数据是存放在State Database中的,如果我们直接修改了CouchDB的数据,那么接下来的查询和事务是直接基于修改后的CouchDB的,并不会去检查区块链中的记录,所以理论上是可以通过直接改CouchDB来实现业务数据的修改。
    我们以官方的Marble为例,看看修改CouchDB会怎么样?
    具体操作步骤如下:
    1.Install,instantiate和初始化数据:
    peer chaincode install -n marbles02 -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/marbles02
    
    peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C mychannel -n marbles02 -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/marbles02 -c '{"Args":["init"]}' -P "OR ('Org1MSP.member','Org2MSP.member')"
    
    peer chaincode invoke -o orderer.example.com:7050  --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem  -C mychannel -n marbles02 -c '{"Args":["initMarble","marble2","red","50","tom"]}'
    
    peer chaincode query -C mychannel -n marbles02 -c '{"Args":["readMarble","marble2"]}'

    我们可以看到通过curl直接查询CouchDB中的数据:

    curl http://192.168.100.129:5984/mychannel/marbles02%00marble2

    {"_id":"marbles02u0000marble2","_rev":"1-a1844f47b9ed94294b430c9a9a6f543b","chaincodeid":"marbles02","data":{"docType":"marble","name":"marble2","color":"red","size":50,"owner":"tom"},"version":"6:0"}

    如果我们要修改其中的数据,把颜色改成green,大小改成10,那么我们可以运行:

    curl -X PUT http://192.168.100.129:5984/mychannel/marbles02%00marble2 -d '{"_id":"marbles02u0000marble2","_rev":"1-a1844f47b9ed94294b430c9a9a6f543b","chaincodeid":"marbles02","data":{"docType":"marble","name":"marble2","color":"green","size":10,"owner":"tom"},"version":"6:0"}'

    系统返回结果:
    {"ok":true,"id":"marbles02u0000marble2","rev":"2-6ffc6652cfc707f8352a5f06c3ce1ce6"}

    我们在4个CouchDB中都运行这个命令,把4个数据库的数据都改了。
    接下来我们通过ChainCode来查询,看看会怎么样。
    peer chaincode query -C mychannel -n marbles02 -c '{"Args":["readMarble","marble2"]}'
    返回结果:
    Query Result: {"color":"green","docType":"marble","name":"marble2","owner":"tom","size":10}
    可以看到数据已经变成新的值,那么接下来运行其他的Transaction会怎么样?我们试一试转账操作:
    peer chaincode invoke -o orderer.example.com:7050  --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem  -C mychannel -n marbles02 -c '{"Args":["transferMarble","marble2","jerry"]}'
    系统返回成功,我们再查一下呢
    peer chaincode query -C mychannel -n marbles02 -c '{"Args":["readMarble","marble2"]}'
    Query Result: {"color":"green","docType":"marble","name":"marble2","owner":"jerry","size":10}
    所以我们对CouchDB数据库的更改都是有效的,在Fabric看来似乎并不知道我们改了CouchDB的内容。
     
  • 相关阅读:
    51nod 1179 最大的最大公约数 (数论)
    POJ 3685 二分套二分
    POJ 3045 贪心
    LIC
    HDU 1029 Ignatius and the Princess IV
    HDU 1024 Max Sum Plus Plus
    HDU 2389 Rain on your Parade
    HDU 2819 Swap
    HDU 1281 棋盘游戏
    HDU 1083 Courses
  • 原文地址:https://www.cnblogs.com/studyzy/p/7101136.html
Copyright © 2011-2022 走看看