全篇安裝主要參照這篇官方文檔,但中間有很多坑,需要格外注意。本人系統Deepin15.10
必要組件安裝
請參加這位大大的blog,還有這位的,裏面有詳細記錄如何安裝相關組件,建議對照官方文檔中的查看,因爲blog裏面的組件不全。並且,自己親測按照blog中的安裝方法無法適應最新版本,因此建議按照官方的來。注意docker-ce的版本要在18.09以後,否則會報錯;還有就是一定要取消docker必須使用超級賬戶的權限,因爲後續安裝caliper不能用sudo,會報錯。詳情請參見:
最新docker下載請看 http://www.voidcn.com/article/p-zbjykblf-byx.html 需要注意如果要刪除已安裝的docker,尤其是版本裝錯了重裝的,請使用
sudo apt-get remove docker-ce
否則會報錯,說沒有安裝docker
安裝完後改國內源和權限等後續處理請看 https://blog.csdn.net/qq_36148847/article/details/79273591
caliper安裝
由於最新版caliper的原因,很多2019年以前的教程中caliper的用法已經不適用了,因此還是得按照官方的來。
採用官方文檔中 Local NPM install 的安裝方法。 有兩個坑需要注意
1)
npx caliper bind \
--caliper-bind-sut fabric:1.4.0
這個語句現在已經不能用了,請用下面的語句代替
npx caliper bind \
--caliper-bind-sut fabric --caliper-bind-sdk 1.4.0
2)
npx caliper launch master \
--caliper-workspace . \
--caliper-benchconfig benchmarks/scenario/simple/config.yaml \
--caliper-networkconfig networks/fabric/fabric-v1.4.1/2org1peergoleveldb/fabric-go.yaml
這個語句現在也執行不了,現在按照
npx caliper benchmark run --caliper-workspace ./ --caliper-benchconfig benchmarks/scenario/simple/config.yaml --caliper-networkconfig networks/fabric/fabric-v1.4.1/2org1peergoleveldb/fabric-go.yaml
來執行了
上面2)中的語句實際就是執行測試的語句了,但是有個前提,必須在caliper官方的workbench目錄下,該目錄配置有很多測試用的文件
git clone https://github.com/hyperledger/caliper-benchmarks.git
cd caliper-benchmarks
git checkout <your Caliper version>
選擇和caliper相同的版本,如本文選擇的是caliper v0.2.0,則這裏也填 v0.2.0
一定要注意切換版本,否則可能出現測試的標準無法識別的情況。我一開始沒有切版本,結果報了一個無法監控cpu的錯誤(其實我也不知道是不是這個原因導致的,反正切了應該沒錯吧)
使用caliper
大部分教程講到測試成功就沒有下文了,這裏多講一點關於怎麼用的問題。首先,從開始執行的測試中可以看到測試的配置文件主要有兩個。網絡方面注意是 networks/fabric/fabric-v1.4.1/2org1peergoleveldb/fabric-go.yaml, 測試配置爲benchmarks/scenario/simple/config.yaml
打開測試配置文件 benchmarks/scenario/simple/config.yaml,可以見到如下語句
---
test:
clients:
type: local
number: 1
rounds:
- label: Change car owner.
txNumber:
- 100
rateControl:
- type: fixed-rate
opts:
tps: 50
arguments:
assets: 1000
callback: benchmarks/scenario/fabcar/changeCarOwner.js
- label: Query all cars.
txNumber:
- 100
rateControl:
- type: fixed-rate
opts:
tps: 50
arguments:
assets: 1000
startKey: '1'
endKey: '50'
callback: benchmarks/scenario/fabcar/queryAllCars.js
- label: Query a car.
txNumber:
- 100
rateControl:
- type: fixed-rate
opts:
tps: 50
arguments:
assets: 1000
callback: benchmarks/scenario/fabcar/queryCar.js
- label: Create a car.
txNumber:
- 100
rateControl:
- type: fixed-rate
opts:
tps: 50
arguments:
callback: benchmarks/scenario/fabcar/createCar.js
monitor:
type:
- docker
- process
docker:
name:
- all
process:
- command: node
arguments: local-client.js
multiOutput: avg
interval: 1
test裏面round,每個label對應一個測試項,實例中測試的主要是吞吐量,調用callback裏面的js文件進行測試。隨意打開一個js文件,如示例sample中的open.js:
'use strict';
module.exports.info = 'opening accounts';
let account_array = [];
let txnPerBatch;
let initMoney;
let bc, contx;
module.exports.init = function(blockchain, context, args) {
if(!args.hasOwnProperty('money')) {
return Promise.reject(new Error('simple.open - \'money\' is missed in the arguments'));
}
if(!args.hasOwnProperty('txnPerBatch')) {
args.txnPerBatch = 1;
}
initMoney = args.money;
txnPerBatch = args.txnPerBatch;
bc = blockchain;
contx = context;
return Promise.resolve();
};
const dic = 'abcdefghijklmnopqrstuvwxyz';
/**
* Generate string by picking characters from dic variable
* @param {*} number character to select
* @returns {String} string generated based on @param number
*/
function get26Num(number){
let result = '';
while(number > 0) {
result += dic.charAt(number % 26);
number = parseInt(number/26);
}
return result;
}
let prefix;
/**
* Generate unique account key for the transaction
* @returns {String} account key
*/
function generateAccount() {
// should be [a-z]{1,9}
if(typeof prefix === 'undefined') {
prefix = get26Num(process.pid);
}
return prefix + get26Num(account_array.length+1);
}
/**
* Generates simple workload
* @returns {Object} array of json objects
*/
function generateWorkload() {
let workload = [];
for(let i= 0; i < txnPerBatch; i++) {
let acc_id = generateAccount();
account_array.push(acc_id);
if (bc.bcType === 'fabric') {
workload.push({
chaincodeFunction: 'open',
chaincodeArguments: [acc_id, initMoney.toString()],
});
} else {
workload.push({
'verb': 'open',
'account': acc_id,
'money': initMoney
});
}
}
return workload;
}
module.exports.run = function() {
let args = generateWorkload();
return bc.invokeSmartContract(contx, 'simple', 'v0', args, 100);
};
module.exports.end = function() {
return Promise.resolve();
};
module.exports.account_array = account_array;
關鍵在於module.export.run中,返回的bc.invokeSmartContract即調用鏈碼功能,其中第二項爲鏈碼名,第三項爲版本,第四項即參數,最後一項是啥我還不清楚,後面在研究。
注意參數的設置在generateWorkload裏面,這是用戶自定義的一個函數,但是其實也可以不這麼寫。再看看另外一個測試查詢藉口的代碼query.js:
'use strict';
module.exports.info = 'querying accounts';
let bc, contx;
let account_array;
module.exports.init = function(blockchain, context, args) {
const open = require('./open.js');
bc = blockchain;
contx = context;
account_array = open.account_array;
return Promise.resolve();
};
module.exports.run = function() {
const acc = account_array[Math.floor(Math.random()*(account_array.length))];
if (bc.bcType === 'fabric') {
let args = {
chaincodeFunction: 'query',
chaincodeArguments: [acc],
};
return bc.bcObj.querySmartContract(contx, 'simple', 'v0', args, 10);
} else {
// NOTE: the query API is not consistent with the invoke API
return bc.queryState(contx, 'simple', 'v0', acc);
}
};
module.exports.end = function() {
// do nothing
return Promise.resolve();
};
看起來似乎要短很多,原因在於這裏沒有隨機生成用戶名字的代碼,轉而從open.js的執行結果中取出了生成名字列表,注意開始init的部分。open.js的列表導出在最後一句
module.exports.account_array = account_array;
這些東西我還沒有摸索清楚,因爲不是很會JavaScript,後面在慢慢弄。
還有一點,所有要測試的鏈碼都要在通道和peer上安裝,不然你是測試不了的。測試代碼會自動安裝,但是需要配置要安裝的鏈碼和鏈碼的路徑。配置文件在 networks/fabric/fabric-v1.4.1/2org1peergoleveldb/fabric-go.yaml裏面。
channels:
mychannel:
configBinary: networks/fabric/config_solo/mychannel.tx
created: false
orderers:
- orderer.example.com
peers:
peer0.org1.example.com:
eventSource: true
peer0.org2.example.com:
eventSource: true
chaincodes:
# - id: marbles
# version: v0
# language: golang
# path: fabric/samples/marbles/go
# metadataPath: src/fabric/samples/marbles/go/metadata
# - id: drm
# version: v0
# language: golang
# path: fabric/scenario/drm/go
- id: simple
version: v0
language: golang
path: fabric/scenario/simple/go
# - id: smallbank
# version: v0
# language: golang
# path: fabric/scenario/smallbank/go
- id: abstore
version: v0
language: golang
path: fabric/scenario/abstore/go
chaincodes下面就是配置要安裝的鏈碼的,注意這個path,是從你指定的workspace下src目錄開始算的,即完整地址爲 你的workspace/src/path
大致就這些了,我也就研究了這麼多,後續有進展還會繼續記錄。