Hyperledger caliper 安装记录

介绍

Caliper 是一个区块链性能测试框架,可用于测试不同的区块链实现,由华为公司开发并贡献给 Hyperledger。本文介绍如何在 ubuntu 系统下安装 caliper 并完成简单测试,最后会说明安装过程中的错误解决。

Pre-requisites

需要安装的基础环境如下:

  • make,g++
  • NodeJS 8.X
  • node-gyp
  • Docker
  • Docker-compose

1. 安装 make,g++ 编译工具

1
sudo apt-get install make g++

2. 安装node.js

ubuntu 支持 nodesouce 的二进制安装脚本,命令如下:

1
2
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs

安装完成后查看 node 与 npm 的版本:

1
2
3
4
$ node -v
v8.12.0
$ npm -v
6.4.1

3. 安装 node-gyp

npm 全局安装 node-gyp:

1
sudo npm install -g node-gyp

4. 安装 Docker

  • 由于 apt 源使用HTTPS以确保软件下载过程中不被篡改。因此,我们首先需要添加使用HTTPS传输的软件包以及CA证书。

    1
    2
    3
    4
    5
    $ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
  • 为了确认所下载软件包的合法性,需要添加软件源的 GPG 秘钥

    1
    $ curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
  • 然后,我们需要向 sources.list 中添加 Docker 软件源

    1
    2
    3
    4
    $ sudo add-apt-repository \
    "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
    $(lsb_release -cs) \
    stable"

    以上命令会添加稳定版本的Docker CE apt 镜像源。

  • 更新 apt 软件包缓存,并安装 docker-ce:

    1
    2
    3
    $ sudo apt-get update

    $ sudo apt-get install docker-ce
  • 查看 Docker 版本:

    1
    2
    $ docker -v
    Docker version 18.06.0-ce, build 0ffa825
  • 启动 Docker CE

    1
    2
    $ sudo systemctl enable docker
    $ sudo systemctl start docker
  • 建立 docker 用户组

    默认情况下,docker 命令会使用 Unix socket 与 Docker 引擎通讯。而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组。

    1
    $ sudo groupadd docker

    其实一般按照上面的方法安装 Docker 后就已经创建好 docker 用户组了,可以使用 $ cat /etc/group | grep docker 命令来验证,所以就不需要再建立 docker 用户组了,再建立也会报错提示用户组已存在的。

  • 将当前用户加入 docker 用户组:

    1
    $ sudo usermod -aG docker $USER

    下次登录时即可方便的使用 docker 命令。

  • 测试 Docker 是否安装正确

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    $ docker run hello-world
    Unable to find image 'hello-world:latest' locally
    latest: Pulling from library/hello-world
    9db2ca6ccae0: Pull complete
    Digest: sha256:4b8ff392a12ed9ea17784bd3c9a8b1fa3299cac44aca35a85c90c5e3c7afacdc
    Status: Downloaded newer image for hello-world:latest

    Hello from Docker!
    This message shows that your installation appears to be working correctly.

    To generate this message, Docker took the following steps:
    1. The Docker client contacted the Docker daemon.
    2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
    3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
    4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

    To try something more ambitious, you can run an Ubuntu container with:
    $ docker run -it ubuntu bash

    Share images, automate workflows, and more with a free Docker ID:
    https://hub.docker.com/

    For more examples and ideas, visit:
    https://docs.docker.com/engine/userguide/
  • 配置镜像加速器

    国内从 Docker Hub 拉取镜像有时会遇到困难,此时可以配置镜像加速器。Docker 官方和国内很多云服务商都提供了国内加速器服务,例如:

    当配置某一个加速器地址之后,若发现拉取不到镜像,请切换到另一个加速器地址。

    国内各大云服务商均提供了 Docker 镜像加速服务,建议根据运行 Docker 的云平台选择对应的镜像加速服务。

    我们以 Docker 官方加速器 https://registry.docker-cn.com 为例进行介绍。

    /etc/docker/daemon.json 中写入如下内容(如果文件不存在则创建)

    1
    2
    3
    4
    5
    {
    "registry-mirrors": [
    "https://registry.docker-cn.com"
    ]
    }

    之后重新启动服务

    1
    2
    $ sudo systemctl daemon-reload
    $ sudo systemctl restart docker

    5. 安装 Docker-compose

  • 通过二进制包来安装,从 官方 GitHub Release 处直接下载编译好的二进制文件即可。

    1
    2
    3
    $ sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose

    $ sudo chmod +x /usr/local/bin/docker-compose
  • 查看 Docker compose 版本

    1
    2
    $ docker-compose --version
    docker-compose version 1.22.0, build f46880fe

Clone caliper repository

从 GitHub 克隆 caliper 代码仓库:

1
git clone https://github.com/hyperledger/caliper.git

进入 caliper 目录并运行 npm install 安装依赖包:

1
2
cd caliper/
npm install

Install fabric SDKs

在 caliper 目录下本地安装 fabric SDKs:

1
npm install grpc@1.10.1 fabric-ca-client fabric-client

以上命令默认安装 fabric 最新版本的 SDKs,但是由于 caliper 验证过的最新版本是 v1.1.0,所以我们最好安装 v1.1.0 版本:

1
npm install fabric-ca-client@1.1.0 fabric-client@1.1.0

Run benchmark

性能测试示例在benchmark目录下,用法如下:

1
node benchmark/simple/main.js -c yourconfig.json -n yournetwork.json
  • -c 用于指定区块链的配置文件,不指定的话默认为config.json
  • -n 用于指定区块链网络配置文件,不指定的话由-c指定的配置文件定义。

运行一个 simple 的实例:

1
node benchmark/simple/main.js

生成的报告如下:


Bugs

运行测试遇到 REQUEST_TIMEOUT 的问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
$ node benchmark/simple/main.js 
TAP version 13
# #######Caliper Test######
docker-compose -f network/fabric/simplenetwork/docker-compose.yaml up -d
Creating network "simplenetwork_default" with the default driver
Creating ca_peerOrg1 ... done
Creating simplenetwork_peer_1 ... done
Creating orderer.example.com ... done
Creating ca_peerOrg2 ... done
Creating simplenetwork_ca_1 ... done
Creating peer1.org2.example.com ... done
Creating peer0.org1.example.com ... done
Creating peer1.org1.example.com ... done
Creating peer0.org2.example.com ... done
# create mychannel......
ok 1 created mychannel successfully
# Sleep 5s......
# Join channel......
# join mychannel
ok 2 Successfully joined mychannel
# install all chaincodes......
info: [packager/Golang.js]: packaging GOLANG from contract/fabric/simple/go
info: [packager/Golang.js]: packaging GOLANG from contract/fabric/simple/go
ok 3 Installed chaincode simple successfully in all peers
# Instantiate chaincode......
error: [Peer.js]: sendProposal - timed out after:120000
error: [Peer.js]: sendProposal - timed out after:120000
error: [Peer.js]: sendProposal - timed out after:120000
error: [Peer.js]: sendProposal - timed out after:120000
error: [client-utils.js]: sendPeersProposal - Promise is rejected: Error: REQUEST_TIMEOUT
at Timeout._onTimeout (/home/user1/go/src/github.com/hyperledger/caliper/node_modules/fabric-client/lib/Peer.js:124:19)
at ontimeout (timers.js:498:11)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:290:5)
error: [client-utils.js]: sendPeersProposal - Promise is rejected: Error: REQUEST_TIMEOUT
at Timeout._onTimeout (/home/user1/go/src/github.com/hyperledger/caliper/node_modules/fabric-client/lib/Peer.js:124:19)
at ontimeout (timers.js:498:11)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:290:5)
error: [client-utils.js]: sendPeersProposal - Promise is rejected: Error: REQUEST_TIMEOUT
at Timeout._onTimeout (/home/user1/go/src/github.com/hyperledger/caliper/node_modules/fabric-client/lib/Peer.js:124:19)
at ontimeout (timers.js:498:11)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:290:5)
error: [client-utils.js]: sendPeersProposal - Promise is rejected: Error: REQUEST_TIMEOUT
at Timeout._onTimeout (/home/user1/go/src/github.com/hyperledger/caliper/node_modules/fabric-client/lib/Peer.js:124:19)
at ontimeout (timers.js:498:11)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:290:5)
not ok 4 Failed to instantiate chaincodes, Error: Failed to send instantiate due to error: Error: Failed to send instantiate Proposal or receive valid response. Response null or status is not 200. exiting... at Client.newDefaultKeyValueStore.then.then.then.then (/home/user1/go/src/github.com/hyperledger/caliper/src/fabric/e2eUtils.js:372:19) at <anonymous> at process._tickCallback (internal/process/next_tick.js:189:7) at Client.newDefaultKeyValueStore.then.then.then.then.then (/home/user1/go/src/github.com/hyperledger/caliper/src/fabric/e2eUtils.js:385:15) at <anonymous> at process._tickCallback (internal/process/next_tick.js:189:7)
---
operator: fail
at: chaincodes.reduce.then.catch (/home/user1/go/src/github.com/hyperledger/caliper/src/fabric/instantiate-chaincode.js:60:19)
stack: |-
Error: Failed to instantiate chaincodes, Error: Failed to send instantiate due to error: Error: Failed to send instantiate Proposal or receive valid response. Response null or status is not 200. exiting...
at Client.newDefaultKeyValueStore.then.then.then.then (/home/user1/go/src/github.com/hyperledger/caliper/src/fabric/e2eUtils.js:372:19)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:189:7)
at Client.newDefaultKeyValueStore.then.then.then.then.then (/home/user1/go/src/github.com/hyperledger/caliper/src/fabric/e2eUtils.js:385:15)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:189:7)
at Test.assert [as _assert] (/home/user1/go/src/github.com/hyperledger/caliper/node_modules/tape/lib/test.js:224:54)
at Test.bound [as _assert] (/home/user1/go/src/github.com/hyperledger/caliper/node_modules/tape/lib/test.js:76:32)
at Test.fail (/home/user1/go/src/github.com/hyperledger/caliper/node_modules/tape/lib/test.js:317:10)
at Test.bound [as fail] (/home/user1/go/src/github.com/hyperledger/caliper/node_modules/tape/lib/test.js:76:32)
at chaincodes.reduce.then.catch (/home/user1/go/src/github.com/hyperledger/caliper/src/fabric/instantiate-chaincode.js:60:19)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:189:7)
...
fabric.installSmartContract() failed, Error: Fabric: instantiate chaincodes failed
at chaincodes.reduce.then.catch (/home/user1/go/src/github.com/hyperledger/caliper/src/fabric/instantiate-chaincode.js:61:31)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:189:7)
[Transaction Info] - Submitted: 0 Succ: 0 Fail:0 Unfinished:0
unexpected error, Error: Fabric: instantiate chaincodes failed
at chaincodes.reduce.then.catch (/home/user1/go/src/github.com/hyperledger/caliper/src/fabric/instantiate-chaincode.js:61:31)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:189:7)
docker-compose -f network/fabric/simplenetwork/docker-compose.yaml down;docker rm $(docker ps -aq);docker rmi $(docker images dev* -q)
Stopping peer0.org1.example.com ... done
Stopping peer0.org2.example.com ... done
Stopping peer1.org1.example.com ... done
Stopping peer1.org2.example.com ... done
Stopping simplenetwork_ca_1 ... done
Stopping ca_peerOrg2 ... done
Stopping orderer.example.com ... done
Stopping ca_peerOrg1 ... done
Removing peer0.org1.example.com ... done
Removing peer0.org2.example.com ... done
Removing peer1.org1.example.com ... done
Removing peer1.org2.example.com ... done
Removing simplenetwork_ca_1 ... done
Removing ca_peerOrg2 ... done
Removing simplenetwork_peer_1 ... done
Removing orderer.example.com ... done
Removing ca_peerOrg1 ... done
Removing network simplenetwork_default
"docker rm" requires at least 1 argument.
See 'docker rm --help'.

Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...]

Remove one or more containers
"docker rmi" requires at least 1 argument.
See 'docker rmi --help'.

Usage: docker rmi [OPTIONS] IMAGE [IMAGE...]

Remove one or more images

1..4
# tests 4
# pass 3
# fail 1

问题解决:

  1. 首先需要检查环境依赖是否正确安装,尤其是 node-gyp 包。

  2. 然后查看 npm 包版本信息及 docker 镜像信息:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $ npm ls fabric-client
    caliper@0.1.0 /home/user1/go/src/github.com/hyperledger/caliper
    └── fabric-client@1.1.0

    $ npm ls fabric-ca-client
    caliper@0.1.0 /home/user1/go/src/github.com/hyperledger/caliper
    └── fabric-ca-client@1.1.0

    $ npm ls grpc
    caliper@0.1.0 /home/user1/go/src/github.com/hyperledger/caliper
    ├─┬ fabric-client@1.1.0
    │ └── grpc@1.10.1 deduped
    └── grpc@1.10.1

    需确认无误。因为 caliper 在创建 fabric 网络时默认是使用的 fabric v1.1.0 版本,docker 下载的 peer、Orderer、ca 镜像也是 x86_64-v1.1.0 版本,所以 fabric SDKs 的 版本必须一致。

    1
    2
    3
    4
    5
    $ docker image ls
    REPOSITORY TAG IMAGE ID CREATED SIZE
    hyperledger/fabric-ca x86_64-1.1.0 72617b4fa9b4 6 months ago 299MB
    hyperledger/fabric-orderer x86_64-1.1.0 ce0c810df36a 6 months ago 180MB
    hyperledger/fabric-peer x86_64-1.1.0 b023f9be0771 6 months ago 187MB
  3. 修改请求超时时间

    在一台虚拟机里面安装的测试环境,搭建的 fabric 网络将会运行有7个 nodes/containers(1 orderer,2 CAs,4 peers),可能由于虚拟机性能的原因,原本 2 分钟的请求超时时间可能不足以 instantiate chaincode(需要构建一个 docker 镜像,并在每个 peer 中运行 chaincode Init 函数)。所以应该尝试增加 timeout 的值。修改 src/fabric/e2eUtils.js 第211行:

    1
    Client.setConfigSetting('request-timeout', 120000);

    将 120000 增加到 480000。

    参考链接:

    Instantiate chaincode…… #118

    instantiate chaincodes Error #137