前言:根据操作系统版本不同,部署环境不同,一些细节差别可能造成测试失败等问题,此文仅做参考,应以实际应用为主。

参考官方文档:压力测试指南 — FISCO BCOS v2.9.0 文档

一、环境要求:

  • 部署Caliper的计算机需要有外网权限;

  • 操作系统版本需要满足以下要求:Ubuntu >= 16.04、CentOS >= 7或MacOS >= 10.14;

  • 部署Caliper的计算机需要安装有以下软件:python 2.7、make、g++、gcc及git。

具体细节见此文档:FISCO-BCOS 十三、Ubuntu配置Caliper基本环境_奈何不吃鱼的博客-CSDN博客

二、安装NodeJS

# 安装nvm
curl -o- https://gitee.com/mirrors/nvm/raw/v0.33.2/install.sh | bash# 加载nvm配置
source ~/.$(basename $SHELL)rc
# 安装Node.js 8
nvm install 8
# 使用Node.js 8
nvm use 8

三、部署 Docker

# 更新包索引
sudo apt-get update
# 安装基础依赖库
sudo apt-get install \apt-transport-https \ca-certificates \curl \gnupg-agent \software-properties-common
# 添加Docker官方GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# 添加docker仓库
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
# 更新包索引
sudo apt-get update
# 安装Docker
sudo apt-get install docker-ce docker-ce-cli containerd.io

加入Docker用户组

sudo groupadd docker
sudo usermod -aG docker $USER

安装Docker Compose

sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

四、Caliper部署

1.建立一个工作目录

mkdir benchmarks && cd benchmarks

2.对NPM项目进行初始化

npm init
# 不需要填写项目信息的话可以直接执行
npm init -y

3.安装caliper-cli

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

4.验证caliper-cli安装成功

npx caliper --version

5.绑定FISCO BCOS,可以采用如下方式进行绑定:

npx caliper bind --caliper-bind-sut fisco-bcos --caliper-bind-sdk latest

         五、快速体验FISCO BCOS基准测试

1.在工作目录下下载预定义测试用例

git clone https://github.com/vita-dounai/caliper-benchmarks.git

2.执行HelloWorld合约测试

npx caliper benchmark run --caliper-workspace caliper-benchmarks --caliper-benchconfig benchmarks/samples/fisco-bcos/helloworld/config.yaml  --caliper-networkconfig networks/fisco-bcos/4nodes1group/fisco-bcos.json

3.执行Solidity版转账合约测

npx caliper benchmark run --caliper-workspace caliper-benchmarks --caliper-benchconfig benchmarks/samples/fisco-bcos/transfer/solidity/config.yaml  --caliper-networkconfig networks/fisco-bcos/4nodes1group/fisco-bcos.json

P1:

解决方法:

修改三个配置文件:

路径:~/benchmarks/node_modules/@hyperledger/caliper-fisco-bcos/lib/fiscoBcos.js

修改为:

/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/'use strict';const {BlockchainInterface,CaliperUtils
} = require('@hyperledger/caliper-core');
const installSmartContractImpl = require('./installSmartContract');
const invokeSmartContractImpl = require('./invokeSmartContract');
const generateRawTransactionImpl = require('./generateRawTransactions');
const sendRawTransactionImpl = require('./sendRawTransactions');
const Color = require('./common').Color;
const commLogger = CaliperUtils.getLogger('fiscoBcos.js');/*** Implements {BlockchainInterface} for a FISCO BCOS backend.*/
class FiscoBcos extends BlockchainInterface {/*** Create a new instance of the {FISCO BCOS} class.* @param {string} config_path The absolute path of the FISCO BCOS network configuration file.* @param {string} workspace_root The absolute path to the root location for the application configuration files.*/constructor(config_path, workspace_root) {super(config_path);this.bcType = 'fisco-bcos';this.workspaceRoot = workspace_root;this.fiscoBcosSettings = CaliperUtils.parseYaml(this.configPath)['fisco-bcos'];if (this.fiscoBcosSettings.network && this.fiscoBcosSettings.network.authentication) {for (let k in this.fiscoBcosSettings.network.authentication) {this.fiscoBcosSettings.network.authentication[k] = CaliperUtils.resolvePath(this.fiscoBcosSettings.network.authentication[k], workspace_root);}}}/*** Initialize the {FISCO BCOS} object.* @async* @return {Promise<object>} The promise for the result of the execution.*/async init() {return Promise.resolve();}/*** Deploy the smart contract specified in the network configuration file to all nodes.* @async*/async installSmartContract() {const fiscoBcosSettings = this.fiscoBcosSettings;try {await installSmartContractImpl.run(fiscoBcosSettings, this.workspaceRoot);} catch (error) {commLogger.error(Color.error(`FISCO BCOS smart contract install failed: ${(error.stack ? error.stack : error)}`));throw error;}}/*** Get a context for subsequent operations* 'engine' attribute of returned context object must be reserved for benchmark engine to extend the context*  engine = {*   submitCallback: callback which must be called once new transaction(s) is submitted, it receives a number argument which tells how many transactions are submitted* }* @param {String} name name of the context* @param {Object} args adapter specific arguments* @param {Integer} clientIdx the client index* @return {Promise<object>} The promise for the result of the execution.*/async getContext(name, args, clientIdx) {return Promise.resolve();}/*** Release a context as well as related resources* @param {Object} context adapter specific object* @return {Promise<object>} The promise for the result of the execution.*/async releaseContext(context) {return Promise.resolve();}/*** Invoke the given smart contract according to the specified options. Multiple transactions will be generated according to the length of args.* @param {object} context The FISCO BCOS context returned by {getContext}.* @param {string} contractID The name of the smart contract.* @param {string} contractVer The version of the smart contract.* @param {Array} args Array of JSON formatted arguments for transaction(s). Each element contains arguments (including the function name) passing to the smart contract. JSON attribute named transaction_type is used by default to specify the function name. If the attribute does not exist, the first attribute will be used as the function name.* @param {number} timeout The timeout to set for the execution in seconds.* @return {Promise<object>} The promise for the result of the execution.*/async invokeSmartContract(context, contractID, contractVer, args, timeout) {let promises = [];try {args.forEach((arg) => {let fcn = null;let fcArgs = [];for (let key in arg) {if (key === 'transaction_type') {fcn = arg[key].toString();} else {fcArgs.push(arg[key].toString());}}promises.push(invokeSmartContractImpl.run(context, this.fiscoBcosSettings, contractID, fcn, fcArgs, this.workspaceRoot));});return await Promise.all(promises);} catch (error) {commLogger.error(Color.error(`FISCO BCOS smart contract invoke failed: ${(error.stack ? error.stack : JSON.stringify(error))}`));throw error;}}/*** Query state from the ledger* @param {Object} context The FISCO BCOS context returned by {getContext}* @param {String} contractID Identity of the contract* @param {String} contractVer Version of the contract* @param {String} key lookup key* @param {String} fcn The smart contract query function name* @return {Promise<object>} The result of the query.*/async queryState(context, contractID, contractVer, key, fcn) {try {return invokeSmartContractImpl.run(context, this.fiscoBcosSettings, contractID, fcn, key, this.workspaceRoot, true);} catch (error) {commLogger.error(Color.error(`FISCO BCOS smart contract query failed: ${(error.stack ? error.stack : error)}`));throw error;}}/*** Generate an raw transaction and store in local file* @param {Object} context The FISCO BCOS context returned by {getContext}* @param {String} contractID Identity of the contract* @param {Object} arg Arguments of the transaction* @param {String} file File path which will be used to store then transaction* @return {TaskStatus} Indicates whether the transaction is written to the file successfully or not*/async generateRawTransaction(context, contractID, arg, file) {return generateRawTransactionImpl.run(this.fiscoBcosSettings, this.workspaceRoot, context, contractID, arg, file);}/*** Send raw transactions* @param {Object} context The FISCO BCOS context returned by {getContext}* @param {Array} transactions List of raw transactions* @return {Promise} The promise for the result of the execution*/async sendRawTransaction(context, transactions) {return sendRawTransactionImpl.run(this.fiscoBcosSettings, context, transactions);}
}module.exports = FiscoBcos;

路径: ~/benchmarks/node_modules/@hyperledger/caliper-fisco-bcos/lib/channelPromise.js

修改为:

/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/'use strict';const tls = require('tls');
const fs = require('fs');
const net = require('net');
const uuidv4 = require('uuid/v4');
const events = require('events');/*** NetworkError exception class thrown in socket connection*/
class NetworkError extends Error {/**** @param {String} msg exception message*/constructor(msg) {super(msg);this.name = 'NetworkError';}
}let emitters = new Map();
let buffers = new Map();
let sockets = new Map();
let lastBytesRead = new Map();/*** Parse response returned by node* @param {Buffer} response Node's response*/
function parseResponse(response) {let seq = response.slice(6, 38).toString();let result = JSON.parse(response.slice(42).toString());let emitter = emitters.get(seq);if(!emitter) {//Stale message receievedreturn;}emitter = emitter.emitter;if (emitter) {let readOnly = Object.getOwnPropertyDescriptor(emitter, 'readOnly').value;if (readOnly) {if (result.error || result.result !== undefined ) {emitter.emit('gotresult', result);}} else {if (result.error || result.status || (result.result && result.result.status)) {emitter.emit('gotresult', result);} else {if (!result.result) {throw new NetworkError(`unknown message receieved, seq=${seq}, data=${response.toString()}`);}}}} else {throw new NetworkError(`unknown owner message receieved, seq=${seq}, data=${response.toString()}`);}
}/*** Create a new TLS socket* @param {String} ip IP of channel server* @param {Number} port Port of channel server* @param {Object} authentication A JSON object contains certificate file path, private key file path and CA file path* @return {TLSSocket} A new TLS socket*/
function createNewSocket(ip, port, authentication) {let secureContextOptions = {key: fs.readFileSync(authentication.key),cert: fs.readFileSync(authentication.cert),ca: fs.readFileSync(authentication.ca),ecdhCurve: 'secp256k1',};let secureContext = tls.createSecureContext(secureContextOptions);let socket = new net.Socket();socket.connect(port, ip);let clientOptions = {rejectUnauthorized: false,secureContext: secureContext,socket: socket};let tlsSocket = tls.connect(clientOptions);tlsSocket.on('error', function (error) {throw new Error(error);});let socketID = `${ip}:${port}`;lastBytesRead.set(socketID, 0);tlsSocket.on('data', function (data) {let response = null;if (data instanceof Buffer) {response = data;}else {response = Buffer.from(data, 'ascii');}if (!buffers.has(socketID)) {// First time to read data from this socketlet expectedLength = null;if (tlsSocket.bytesRead - lastBytesRead.get(socketID) >= 4) {expectedLength = response.readUIntBE(0, 4);}if (!expectedLength || tlsSocket.bytesRead < lastBytesRead.get(socketID) + expectedLength) {buffers.set(socketID, {expectedLength: expectedLength,buffer: response});} else {lastBytesRead.set(socketID, lastBytesRead.get(socketID) + expectedLength);parseResponse(response);buffers.delete(socketID);}} else {// Multiple readinglet cache = buffers.get(socketID);cache.buffer = Buffer.concat([cache.buffer, response]);if (!cache.expectedLength && tlsSocket.bytesRead - lastBytesRead.get(socketID) >= 4) {cache.expectedLength = cache.buffer.readUIntBE(0, 4);}if (cache.expectedLength && tlsSocket.bytesRead - lastBytesRead.get(socketID) >= cache.expectedLength) {lastBytesRead.set(socketID, lastBytesRead.get(socketID) + cache.expectedLength);parseResponse(buffers.get(socketID).buffer);buffers.delete(socketID);}}});return tlsSocket;
}/*** Prepare the data which will be sent to channel server* @param {String} data JSON string of load* @return {Object} UUID and packaged data*/
function packageData(data) {const headerLength = 4 + 2 + 32 + 4;let length = Buffer.alloc(4);length.writeUInt32BE(headerLength + data.length);let type = Buffer.alloc(2);type.writeUInt16BE(0x12);let uuid = uuidv4();uuid = uuid.replace(/-/g, '');let seq = Buffer.from(uuid, 'ascii');let result = Buffer.alloc(4);result.writeInt32BE(0);let msg = Buffer.from(data, 'ascii');return {'uuid': uuid,'packagedData': Buffer.concat([length, type, seq, result, msg])};
}/*** Clear context when a message got response or timeout* @param {String} uuid The ID of an `channelPromise`request*/
function clearContext(uuid) {clearTimeout(emitters.get(uuid).timer);emitters.delete(uuid);buffers.delete(uuid);
}/*** Return channel promise for a request* @param {Object} node A JSON object which contains IP and port configuration of channel server* @param {Object} authentication A JSON object contains certificate file path, private key file path and CA file path* @param {String} data JSON string of load* @param {Number} timeout Timeout to wait response* @param {Boolean} readOnly Is this request read-only?* @return {Promise} a promise which will be resolved when the request is satisfied*/
function channelPromise(node, authentication, data, timeout, readOnly = false) {let ip = node.ip;let port = node.channelPort;let connectionID = `${ip}${port}`;if (!sockets.has(connectionID)) {let newSocket = createNewSocket(ip, port, authentication);newSocket.unref();sockets.set(connectionID, newSocket);}let tlsSocket = sockets.get(connectionID);let dataPackage = packageData(JSON.stringify(data));let uuid = dataPackage.uuid;tlsSocket.socketID = uuid;let packagedData = dataPackage.packagedData;let channelPromise = new Promise(async (resolve, reject) => {let eventEmitter = new events.EventEmitter();Object.defineProperty(eventEmitter, 'readOnly', {value: readOnly,writable: false,configurable: false,enumerable: false});eventEmitter.on('gotresult', (result) => {clearContext(uuid);if (result.error) {reject(result);} else {resolve(result);}return; // This `return` is not necessary, but it may can avoid future trap});eventEmitter.on('timeout', () => {clearContext(uuid);reject({ 'error': 'timeout' });return; // This `return` is not necessary, but it may can avoid future trap});emitters.set(uuid, {emitter: eventEmitter,timer: setTimeout(() => {eventEmitter.emit('timeout');}, timeout)});tlsSocket.write(packagedData);});return channelPromise;
}module.exports = channelPromise;

路径:  ~/benchmarks/node_modules/@hyperledger/caliper-fisco-bcos/lib/web3lib/web3sync.js

修改为:

/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/'use strict';const uuidv4 = require('uuid/v4');
const utils = require('./utils');
const Transaction = require('./transactionObject').Transaction;/*** Generate a random number via UUID* @return {Number} random number*/
function genRandomID() {let uuid = uuidv4();uuid = '0x' + uuid.replace(/-/g, '');return uuid;
}/*** Sign a transaction with private key and callback* @param {String} txData transaction data* @param {Buffer} privKey private key* @param {callback} callback callback function* @return {String} signed transaction data*/
function signTransaction(txData, privKey, callback) {let tx = new Transaction(txData);let privateKey = Buffer.from(privKey, 'hex');tx.sign(privateKey);// Build a serialized hex version of the txlet serializedTx = '0x' + tx.serialize().toString('hex');if (callback !== null) {callback(serializedTx);} else {return serializedTx;}
}/*** get transaction data* @param {String} func function name* @param {Array} params params* @return {String} transaction data*/
function getTxData(func, params) {let r = /^\w+\((.*)\)$/g.exec(func);let types = [];if (r[1]) {types = r[1].split(',');}return utils.encodeTxData(func, types, params);
}/*** get signed transaction data* @param {Number} groupId ID of the group where this transaction will be sent to* @param {Buffer} account user account* @param {Buffer} privateKey private key* @param {Buffer} to target address* @param {String} func function name* @param {Array} params params* @param {Number} blockLimit block limit* @return {String} signed transaction data*/
function getSignTx(groupId, account, privateKey, to, func, params, blockLimit) {let txData = getTxData(func, params);let postdata = {data: txData,from: account,to: to,gas: 1000000,randomid: genRandomID(),blockLimit: blockLimit,chainId: 1,groupId: groupId,extraData: '0x0'};return signTransaction(postdata, privateKey, null);
}/*** get signed deploy tx* @param {Number} groupId ID of the group where this transaction will be sent to* @param {Buffer} account user account* @param {Buffer} privateKey private key* @param {Buffer} bin contract bin* @param {Number} blockLimit block limit* @return {String} signed deploy transaction data*/
function getSignDeployTx(groupId, account, privateKey, bin, blockLimit) {let txData = bin.indexOf('0x') === 0 ? bin : ('0x' + bin);let postdata = {data: txData,from: account,to: null,gas: 1000000,randomid: genRandomID(),blockLimit: blockLimit,chainId: 1,groupId: groupId,extraData: '0x0'};return signTransaction(postdata, privateKey, null);
}module.exports.getSignDeployTx = getSignDeployTx;
module.exports.signTransaction = signTransaction;
module.exports.getSignTx = getSignTx;
module.exports.getTxData = getTxData;

修改完成后,进入~/benchmarks/node_modules/@hyperledger/caliper-fisco-bcos目录,编辑该目录下的package.json文件,在"dependencies"中添加一项"secp256k1": "^3.8.0",随后在该目录下执行npm i secp256k1@3.0.0

此时执行测试,成功

FISCO-BCOS 十四、使用Caliper进行压力测试fisco-bcos相关推荐

  1. 《网络安全工程师笔记》 第十四章:渗透简单测试流程

    注:本笔记来自温晓飞老师的网络安全课程 第十四章:渗透简单测试流程 第一章:虚拟化架构与系统部署 第二章:IP地址详解 第三章:进制转换 第四章:DOS基本命令与批处理 第五章:用户与组管理 第六章: ...

  2. Linux下四款Web服务器压力测试工具…

    一.http_load 程序非常小,解压后也不到100K http_load以并行复用的方式运行,用以测试web服务器的吞吐量与负载.但是它不同于大多数压力测试工具,它可以以一个单一的进程运行,一般不 ...

  3. Linux下四款Web服务器压力测试工具(http_load、webbench、ab、siege)介绍

    一.http_load程序非常小,解压后也不到100K http_load以并行复用的方式运行,用以测试web服务器的吞吐量与负载.但是它不同于大多数压力测试工具,它可以以一个单一的进程运行,一般不会 ...

  4. Exchange Server2010系列之十五:Exchange磁盘压力测试

    本文章主要是使用Jetstress 2010测试Exchange的磁盘子系统,用来评估Exchange磁盘子系统的IO性能是否可以满足设计需求.Jetstress 工具通过与可扩展存储引擎 (ESE) ...

  5. fisco bcos用caliper0.2.0进行压力测试的安装配置

    一.前期环境 1. 硬件 需要外网权限 2. 操作系统 版本要求:Ubuntu >= 16.04, CentOS >= 7, MacOS >= 10.14 3. 基础软件 pytho ...

  6. 博客园首页新随笔联系管理订阅 Linux下四款Web服务器压力测试工具(http_load、webbench、ab、siege)介绍

    https://www.cnblogs.com/shipengzhi/archive/2012/10/09/2716766.html

  7. 阿里云Redis性能压力测试(二十)

    文章目录 1.云Redis性能压力测试 2.安装redis-banchmark压测工具 3.压测两节点的Redis集群 4.压测四节点的Redis集群 4.1.扩容集群为四节点 4.2.压力测试 5. ...

  8. 压力测试是什么?为什么要压力测试?怎么使用压力测试?

    想必很多人在第一次接触压力测试时都会发出如同题目中的疑惑,压力测试是什么?为什么要进行压力测试?我第一次接触压力测试是在电脑突然死机的情况下,装机师傅给我重装系统后进行了压力测试后才有所了解:这时候才 ...

  9. 第十三讲:目标设定面对压力 第十四讲:压力完美主义 第十五讲:完美主义

    (注:此为课程第十三课,更新于2017年5月30日) (接上一课) Carpe diem, seize the day--抓住眼前,及时行乐. 让我们沿着这个理念再深入一点,讨论一下自我和谐. 自我和 ...

最新文章

  1. Qt之QByteArray类学习
  2. python selenium模拟键盘_SELENIUM自动化模拟键盘快捷键操作实现解析
  3. 深拷贝与浅拷贝深入理解
  4. 50. Pow(x, n)(递归,穷举)
  5. Ubuntu禁用网卡步骤(重启依然生效)
  6. 晨会分享 知识点二〇一六年五月二十五日
  7. 计算机附件中的超级终端,windows10系统中附件中没有超级终端怎么解决
  8. html文字和图片垂直居中,css如何让图片和文字垂直居中?
  9. Go channel详解
  10. (多元)偏正态分布、正态分布、对数正态分布的随机数的产生(R语言)
  11. 清北毕业生5年来去向大数据:北大偏爱银行,清华更倾向国网,华为堪称最大黑洞-1
  12. 用 Python 编程,假设一年期定期利率为 3.25%,计算一下需要过多少年,一万元的一年定期存款连本带息能翻番?
  13. 微信小程序开发之——用户登录-搭建开发者服务器(2)
  14. 目前最全的机器学习知识结构图(11月1日更新)
  15. 电脑如何破解wifi密码
  16. FPGA数字信号处理(十八)Quartus CIC IP核实现
  17. 消防应急照明系统在某数据中心项目的应用
  18. 【SUMO学习】初级 OSMWebWizard
  19. f2fs mkfs 格式化过程系列 0
  20. 洗稿,技术上怎么判断文章相似性?

热门文章

  1. ZCMU1692-鬼吹灯
  2. 2018UI课程总结(UI理论篇)
  3. 第6季2:基于RTSP协议的实时视频流传输的源码分析
  4. XP日文输入法IME/文件打包下载
  5. Python计算矩阵相乘
  6. 驾照理论考试android应用
  7. vue框架目录结构(全)
  8. 传智播客 .NET面试宝典(2015版)
  9. 同花顺炒股软件下载|炒股软件下载
  10. 关于 The RPC server is unavailable