文章出處

回顧一下我之前的一篇博客,在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":"devincc\u0000a","key":"devincc\u0000a","value":{"rev":"2-a979bf6c2716ecae6d106999f833a59c"}},
{"id":"devincc\u0000b","key":"devincc\u0000b","value":{"rev":"2-ad1c549305fd277097180405f96bdcd8"}},
{"id":"lscc\u0000devincc","key":"lscc\u0000devincc","value":{"rev":"1-05d2cd0b344c4dd8a8d1a3ffd7332544"}},
{"id":"lscc\u0000mycc","key":"lscc\u0000mycc","value":{"rev":"1-2cba0344b1610b9d9254bbafbda5e9b1"}},
{"id":"mycc\u0000a","key":"mycc\u0000a","value":{"rev":"2-588a45b289359afa9dc6e5e7866eaf97"}},
{"id":"mycc\u0000b","key":"mycc\u0000b","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"}

麻煩的是業務數據是“ChainCodeName\u0000數據”這樣的格式的ID,而如果我們要通過這個ID查詢,那么就根本找不到啊!

curl http://192.168.100.129:5984/mychannel/mycc\u0000a
{"error":"not_found","reason":"missing"}

正確的做法是把\u0000替換為%00,也就是說我們的查詢應該是:

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

正確返回結果:
{"_id":"mycc\u0000a","_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":"marbles02\u0000marble2","_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":"marbles02\u0000marble2","_rev":"1-a1844f47b9ed94294b430c9a9a6f543b","chaincodeid":"marbles02","data":{"docType":"marble","name":"marble2","color":"green","size":10,"owner":"tom"},"version":"6:0"}'

系統返回結果:
{"ok":true,"id":"marbles02\u0000marble2","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的內容。
 

文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()