Hyperledger Caliper安装爬坑指南——Deepin15.10

全篇安装主要参照这篇官方文档,但中间有很多坑,需要格外注意。本人系统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 

选择和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

大致就这些了,我也就研究了这么多,后续有进展还会继续记录。

你可能感兴趣的:(Hyperledger,Fabric)