Fabric网络性能测试—–caliper

Hyperledger Caliper是Fabric的一个性能测试框架,本质上是通过Node SDK,不断向Fabric网络发送请求,获得相应,从而计算Fabric网络的性能。性能测试实验是基于已经存在并运行的Fabric网络的,因此在使用caliper模块做测试之前,需要搭建好网络。

下面以caliper提供的官网教程为例,讲解测试过程。

一、Fabric网络启动


1、环境搭建

网络启动之前,需要进行环境搭建。本实验环境配置如下:

系统:Ubuntu 18.04go:1.15node.js: v16.16.0npm: 8.11.0docker: 20.10.17docker-compose:1.26.2

go 安装

下载解压

sudo wget -P /usr/local https://studygolang.com/dl/golang/go1.15.linux-amd64.tar.gz #下载cd /usr/local #转换目录sudo tar -zxvf go1.15.linux-amd64.tar.gz #解压

添加环境变量

sudo vim /etc/profile#环境变量配置文件

将以下内容复制到profile文件中,按I插入,插入完成后按ESC退出插入,输出:wq!保存退出:

export GOROOT=/usr/local/goexport PATH=$PATH:$GOROOT/binexport GOPATH=$HOME/go# 开启go mod,并换源export GO111MODULE=onexport GOPROXY=https://mirrors.aliyun.com/goproxy/ 

更新环境变量

source /etc/profile
2、启动网络

首先按照下面命令启动Fabric官方测试网络

# Pull down the 2.2.5 hyperledger fabric images/binaries and the fabric-samples checked out at tag v2.2.5curl -sSL https://bit.ly/2ysbOFE | bash -s -- 2.2.5 1.5.2cd fabric-samples# Switch to a release-2.2 git branch that has a fix for asset-transfer-basic chaincodegit checkout c3a0e814f1609eda2b2f4403b38e33b8b4a16675# Start up the test-networkcd test-network/./network.sh up createChannel# 官方教程使用的是javascript代码,切换go也行,测试过程与链码使用的语言没有关系./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-javascript -ccl javascript

二、创建caliper工作区


在与fabric-samples同级的目录下,创建caliper工作区,命名为caliper-workspace

mkdir caliper-workspace

在caliper-workspace目录下创建三个名为networks、benchmarks和workload的文件夹。这三个文件夹分别用于存放网络配置文件、基准测试配置文件、工作负载文件网络配置文件记录了Fabric网络连接配置信息,工作负载中的模块会使用该文件提供的信息来与Fabric网络交互;基准测试配置文件定义了测试参数;工作负载文件则是具体的测试代码实现。

cd caliper-workspacemkdir networks benchmarks workload
1、构建网络配置文件

进入network目录,创建一个名为networkConfig.yaml的文件

cd networkstouch networkConfig.yaml

将以下内容写进networkConfig.yaml

# 该文件本质上是一个网络连接配置,SDK使用该文件连接到Fabric网络name: Calier testversion: "2.0.0"caliper:blockchain: fabricchannels:- channelName: mychannelcontracts:- id: basicorganizations:- mspid: Org1MSPidentities:certificates:- name: 'User1'clientPrivateKey:path: '../fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/keystore/priv_sk'clientSignedCert:path: '../fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/signcerts/User1@org1.example.com-cert.pem'connectionProfile:path: '../fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/connection-org1.yaml'discover: true
2、构建工作负载模块

工作负载模块负责与链码交互,完成性能测试。该模块继承来自caliper-core模块的Caliper类——WorkloadModuleBase. 工作负载模块重写了三个方法:

  • initializeWorkloadModule 该方法用来初始化测试需要用到的一些数据。
  • submitTransaction 该方法用来与链码交互,在监控测试期间。
  • cleanupWorkloadModule 该方法用来清理测试后的环境,方便下次测试。

进入workload目录,创建一个名为readAsset.js的文件

cd workloadtouch readAsset.js

readAsset.js代码如下:【该代码只测试查询的效率】

'use strict';const { WorkloadModuleBase } = require('@hyperledger/caliper-core');class MyWorkload extends WorkloadModuleBase {constructor() {super();}async initializeWorkloadModule(workerIndex, totalWorkers, roundIndex, roundArguments, sutAdapter, sutContext) {await super.initializeWorkloadModule(workerIndex, totalWorkers, roundIndex, roundArguments, sutAdapter, sutContext);for (let i=0; i<this.roundArguments.assets; i++) {const assetID = `${this.workerIndex}_${i}`;console.log(`Worker ${this.workerIndex}: Creating asset ${assetID}`);const request = {contractId: this.roundArguments.contractId,contractFunction: 'CreateAsset',invokerIdentity: 'User1',contractArguments: [assetID,'blue','20','penguin','500'],readOnly: false};await this.sutAdapter.sendRequests(request);}}async submitTransaction() {const randomId = Math.floor(Math.random()*this.roundArguments.assets);const myArgs = {contractId: this.roundArguments.contractId,contractFunction: 'ReadAsset',invokerIdentity: 'User1',contractArguments: [`${this.workerIndex}_${randomId}`],readOnly: true};await this.sutAdapter.sendRequests(myArgs);}async cleanupWorkloadModule() {for (let i=0; i<this.roundArguments.assets; i++) {const assetID = `${this.workerIndex}_${i}`;console.log(`Worker ${this.workerIndex}: Deleting asset ${assetID}`);const request = {contractId: this.roundArguments.contractId,contractFunction: 'DeleteAsset',invokerIdentity: 'User1',contractArguments: [assetID],readOnly: false};await this.sutAdapter.sendRequests(request);}}}function createWorkloadModule() {return new MyWorkload();}module.exports.createWorkloadModule = createWorkloadModule;
  1. 构建基准测试文件

benchmarks文件夹下创建一个名为myAssetBenchmark.yaml

cd benchmarkstouch myAssetBenchmark.yaml

myAssetBenchmark.yaml内容如下:

test:# 基准测试的名称name: basic-contract-benchmark# 基准测试详细描述description: test benchmarkworkers:# 指定用于执行工作负载的进程数number: 2# 描述每一个测试回合的设置rounds:# 测试标签,一般为测试链码的名称- label: readAssetdescription: Read asset benchmark# caliper提交交易的时间txDuration: 30# 提交交易的速度控制rateControl:# 速度控制类型,有fixed-rate、fixed-load等,解释可参见https://hyperledger.github.io/caliper/v0.5.0/rate-controllers/type: fixed-loadopts:transactionLoad: 2workload:# 描述需要测试的工作负载文件路径module: workload/readAsset.js# 需要传递给工作负责文件的参数arguments:assets: 10contractId: basic

三、测试


安装依赖

npm install --only=prod @hyperledger/caliper-cli@0.5.0

绑定SDK

npx caliper bind --caliper-bind-sut fabric:2.2

测试

npx caliper launch manager --caliper-workspace ./ --caliper-networkconfig networks/networkConfig.yaml --caliper-benchconfig benchmarks/myAssetBenchmark.yaml --caliper-flow-only-test

在实际使用Caliper测试自己搭建的网络过程中,则需要更改相应的网络配置文件以及基准测试文件。因此明白两个配置文件各个字段的含义是关键。工作负载模块中最核心的是submitTransaction方法,重写该方法只需要更改发送请求的相关参数即可,包括:链码名称、函数名称、函数参数等。另外,仓库地址:https://github.com/hyperledger/caliper-benchmarks ;该项目中的代码可以参考,帮助重写工作负载模块,测试自己搭建的网络。