Hyperledger Fabric CouchDB as the State Database——使用CouchDB


使用CouchDB作為狀態數據庫

狀態數據庫選項

狀態數據庫包括LevelDB和CouchDB。LevelDB是嵌入在peer進程中的默認鍵/值狀態數據庫,CouchDB是一個可選的外部狀態數據庫。與LevelDB鍵/值存儲一樣,CouchDB可以存儲任何以chaincode建模的二進制數據(CouchDB附件函數在內部用於非json二進制數據)。但是,當chaincode值(例如,資產)被建模為JSON數據時,作為JSON文檔存儲,CouchDB支持對chaincode數據進行豐富的查詢。

LevelDB和CouchDB都支持核心chaincode操作,例如獲取和設置一個鍵(資產),並根據鍵進行查詢。鍵可以通過范圍查詢,可以對組合鍵進行建模,以支持針對多個參數的等價查詢。例如,作為所有者的組合鍵,資產id可以用於查詢某個實體擁有的所有資產。這些基於key的查詢可以用於針對賬本的只讀查詢,以及更新總賬的事務。

如果將資產建模為JSON並使用CouchDB,那么就可以使用chaincode中的CouchDB JSON查詢語言對chaincode數據值執行復雜的富查詢,這些類型的查詢對於理解賬本上的內容很有幫助。對於這些類型的查詢,事務協議響應通常對客戶端應用程序有用,但通常不會作為事務提交到排序服務。事實上,也無法保證結果集在chaincode執行與富查詢提交時間之間的穩定性,因此使用富查詢的結果去執行最終的事務更新操作是不合適的,除非可以保證結果集在chaincode執行時間與提交時間之間的穩定性,或者可以處理在后續交易中的潛在變化。例如,如果對Alice所擁有的所有資產執行一個富查詢並將其傳輸給Bob,那么一個新的資產可能會被另一個事務分配給Alice,這是在chaincode執行時間和提交時間之間的另一個事務,可能此過程中會錯過這個“虛值”。

CouchDB作為一個獨立的數據庫進程與peer一起運行,因此在設置、管理和操作方面有額外的考慮。我們可以考慮從默認的嵌入式LevelDB開始,如果需要額外的復雜的富查詢,可以轉移到CouchDB。將chaincode資產數據建模為JSON是一種很好的做法,這樣我們就可以在將來執行需要的復雜的富查詢。

 

使用Chaincode中的CouchDB

大多數chaincode的api都可以使用LevelDB或CouchDB狀態數據庫,例如GetState、PutState、GetStateByRange以及GetStateByPartialCompositeKey等。只有當使用CouchDB作為狀態數據庫和在chaincode中作為JSON的模型資產時,可以使用GetQueryResult API和傳遞一個CouchDB查詢字符串來對狀態數據庫中的JSON執行富查詢。查詢字符串遵循CouchDB JSON查詢語法

fabric項目中的marbles02示例演示了使用來自chaincode的CouchDB查詢。它包括一個getMarblesByOwner()函數,它通過將一個owner id傳遞給chaincode來演示參數化查詢,然后查詢與“marble”docType匹配的JSON文檔的狀態數據,以及owner id使用JSON查詢語法:

{
  "selector":{
    "docType":"marble",
    "owner":<OWNER_ID>
  }
}

為了使JSON查詢更高效,並且對於任何具有排序的JSON查詢,都需要使用CouchDB中的索引。索引可以和chaincode一起打包 /META-INF/statedb/couchdb/indexes目錄。每個索引必須在其自己的文本文件中通過擴展*.json被定義,其中索引定義為JSON格式並引用CouchDB索引JSON語法,例如,為了支持上面的marble查詢,提供了一個關於docType和所有者字段的示例索引:

{
  "index":{
    "fields":[
      "docType",
      "owner"

    ]
  },
  "ddoc":"indexOwnerDoc",
  "name":"indexOwner",
  "type":"json"
}

這里可以找到示例索引。

注意:在1.1 alpha中,必須為索引定義中引用的每個字段指定“數據”封裝器。在隨后的版本中,指定“數據”封裝器的需求可能會被取消。

 在chaincode的META-INF/statedb/couchdb/indexes目錄中的任何索引都將與chaincode一起被打包和安裝在peer上。當chaincode即安裝在peer上,且又在peer的channel上實例化時,該索引將自動部署到peer的channel狀態數據庫(如果已配置為使用CouchDB)。如果是先安裝了chaincode,然后才在channel上實例化該chaincode,那么該索引將會在chaincode實例化的時候進行部署。如果chaincode已經在一個channel上實例化了,然后又在一個peer上安裝了這個chaincode,該索引還是會在chaincode實例化的時候進行部署。

在部署時,索引將自動被chaincode查詢利用。CouchDB可以根據查詢中使用的字段自動確定要使用的索引。或者,在選擇器查詢中,可以使用use_index關鍵字指定索引。

在安裝的chaincode的后續版本中可能存在相同的索引。要更改索引,使用相同的索引名稱,但要更改索引定義。在安裝/實例化,索引定義會重新部署到peer的狀態數據庫。

如果所在channle已經擁有大量的數據,並且隨后安裝了chaincode,那么索引的創建在實例化上可能需要一些時間。類似地,如果channel已經擁有大量的數據並且實例化了后續版本的chaincode,那么創建索引也可能需要一些時間。所以需要盡量避免在這些時間段內調用查詢狀態數據庫的chaincode函數,因為當索引被初始化時,chaincode查詢可能會超時。在事務處理期間,因為塊被提交給賬本總賬,所以索引將自動刷新。

 

CouchDB配置

通過將狀態數據庫配置選項從goleveldb更改為CouchDB,可以將CouchDB作為狀態數據庫啟用。此外,couchDBAddress需要配置為指向由peer使用的CouchDB。如果將CouchDB配置一個用戶名和密碼,那么用戶名和密碼屬性應該包含管理員用戶名和密碼。在couchDBConfig中提供了更多的選項,並在適當的地方進行了記錄。在重啟peer之后,修改過的core.yaml將會立即生效。

當然還可以通過docker環境變量來覆蓋core.yaml值,例如CORE_LEDGER_STATE_STATEDATABASE和CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS。

以下是來自core.yaml的狀態數據庫選項:

state:
  # stateDatabase - options are "goleveldb", "CouchDB"
  # goleveldb - default state database stored in goleveldb.
  # CouchDB - store state database in CouchDB
  stateDatabase: goleveldb
  couchDBConfig:
     # It is recommended to run CouchDB on the same server as the peer, and
     # not map the CouchDB container port to a server port in docker-compose.
     # Otherwise proper security must be provided on the connection between
     # CouchDB client (on the peer) and server.
     couchDBAddress: couchdb:5984
     # This username must have read and write authority on CouchDB
     username:
     # The password is recommended to pass as an environment variable
     # during start up (e.g. LEDGER_COUCHDBCONFIG_PASSWORD).
     # If it is stored here, the file must be access control protected
     # to prevent unintended users from discovering the password.
     password:
     # Number of retries for CouchDB errors
     maxRetries: 3
     # Number of retries for CouchDB errors during peer startup
     maxRetriesOnStartup: 10
     # CouchDB request timeout (unit: duration, e.g. 20s)
     requestTimeout: 35s
     # Limit on the number of records to return per query
     queryLimit: 10000

CouchDB被托管在docker容器中,通過使用Docker Compose腳本來利用Hyperledger Fabric設置CouchDB的username和password的能力,通過已有的環境變量設置,即COUCHDB_USER和COUCHDB_PASSWORD環境變量。

對於在使用Fabric提供的docker映像之外的CouchDB安裝,本地安裝。必須編輯ini文件以設置admin用戶名和密碼。

 

Docker Compose腳本只在創建容器時設置用戶名和密碼。如果要在容器創建后更改用戶名或密碼,則必須對本地.ini文件進行編輯。

注意:在每個peer啟動時都讀取CouchDB的peer選項。

 

補充

Hyperledger Fabric 1.0 從零開始(九)——Fabric多節點集群生產啟動中已經設置了peer和cli的啟動配置,其中沒有加入couchdb,這里補充下一個新的peer編寫方法,希望對各位有幫助。

后續在寫到ca的時候也會將ca啟動部分加入進來。

# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#

version: '2'

services:

  couchdb:
    container_name: couchdb
    image: hyperledger/fabric-couchdb
    # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
    # for example map it to utilize Fauxton User Interface in dev environments.
    ports:
      - "5984:5984"

  peer0.xxx.example.com:
    container_name: peer0.xxx.example.com
    image: hyperledger/fabric-peer
    environment:
      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984

      - CORE_PEER_ID=peer0.xxx.example.com
      - CORE_PEER_NETWORKID=anti
      - CORE_PEER_ADDRESS=peer0.xxx.example.com:7051
      - CORE_PEER_CHAINCODELISTENADDRESS=peer0.xxx.example.com:7052
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.xxx.example.com:7051
      - CORE_PEER_LOCALMSPID=xxxMSP

      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      # the following setting starts chaincode containers on the same
      # bridge network as the peers
      # https://docs.docker.com/compose/networking/
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=anti_default
      - CORE_LOGGING_LEVEL=ERROR
      # - CORE_LOGGING_LEVEL=DEBUG
      - CORE_PEER_GOSSIP_SKIPHANDSHAKE=true
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_PROFILE_ENABLED=false
      - CORE_PEER_TLS_ENABLED=false
      - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
    volumes:
        - /var/run/:/host/var/run/
        - ./crypto-config/peerOrganizations/xxx.example.com/peers/peer0.xxx.example.com/msp:/etc/hyperledger/fabric/msp
        - ./crypto-config/peerOrganizations/xxx.example.com/peers/peer0.xxx.example.com/tls:/etc/hyperledger/fabric/tls
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: peer node start
    ports:
      - 7051:7051
      - 7052:7052
      - 7053:7053
    depends_on:
      - couchdb
    networks:
      default:
        aliases:
          - anti
    extra_hosts:
     - "orderer0.example.com:x.x.x.41"
     - "orderer1.example.com:x.x.x.42"
     - "orderer2.example.com:x.x.x.43"

  cli:
    container_name: cli
    image: hyperledger/fabric-tools
    tty: true
    environment:
      - GOPATH=/opt/gopath
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_LOGGING_LEVEL=ERROR
      # - CORE_LOGGING_LEVEL=DEBUG
      - CORE_PEER_ID=cli
      - CORE_PEER_ADDRESS=peer0.xxx.example.com:7051
      - CORE_PEER_LOCALMSPID=xxxMSP
      - CORE_PEER_TLS_ENABLED=false
      - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/xxx.example.com/peers/peer0.xxx.example.com/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/xxx.example.com/peers/peer0.xxx.example.com/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/xxx.example.com/peers/peer0.xxx.example.com/tls/ca.crt
      - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/xxx.example.com/users/Admin@xxx.example.com/msp
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    volumes:
        - /var/run/:/host/var/run/
        - ./chaincode/go/:/opt/gopath/src/github.com/hyperledger/fabric/antimoth/anti/chaincode/go
        - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
        - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
        - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
    depends_on:
      - peer0.xxx.example.com
    extra_hosts:
     - "orderer0.example.com:x.x.x.41"
     - "orderer1.example.com:x.x.x.42"
     - "orderer2.example.com:x.x.x.43"
     - "peer0.xxxx.example.com:x.x.xx.251"


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM