Hyperledger Caliperの使い方 (改訂版)

前回執筆した[記事](https://qiita.com/jnmt/items/0761ac1023b6050a6760)から色々と変わってきたので、改めてブロックチェーン基盤の性能測定のフレームワークであるHyperledger Caliperの使い方について概説します。

## はじめに

Hyperledgerは、Linux Foundationが推進するオープンソースのブロックチェーン基盤開発プロジェクトです。Hyperledgerプロジェクトでは、FabricやSawtooth、Burrowなど、複数のブロックチェーン基盤が開発されています。これらの実装の全く異なるブロックチェーン基盤を、同一のアプリケーション、同一のワークロードで統一的にベンチマークするためのフレームワークが、Hyperledger Caliperです。

対象のブロックチェーン基盤自体が絶賛開発中な上、Caliperも頻繁に仕様が変わっているように見受けられますが、簡単な使い方と何ができるかについてまとめたいと思います。
本記事の内容は v0.3.0 で確認しました。

## 対応するブロックチェーン基盤

- Hyperledger Besu
- Hyperledger Burrow
- Ethereum
- Hyperledger Fabric
- FISCO BCOS
- Hyperledger Iroha
- Hyperledger Sawtooth

## 準備

[こちら](https://hyperledger.github.io/caliper/v0.3/installing-caliper/)に色々なインストール方法が記載されていますが、ここでは一番手っ取り早いと思われるNPMによるローカルインストールを試します。

**前提**

- node-gyp, python2, make, git (ビルド用)
- Node.js v8.X LTS or v10.X LTS (Caliper実行用)
- Docker and Docker Compose (サンプルネットワークでの実行用)

**インストール**

インストール場所はどこでもかまいませんが、以下のように、サンプルワークロードや設定ファイルが入ったリポジトリをクローンしてきて、そこにインストールすると後で設定ファイルを指定するときに都合がよいです。最後にコマンドを実行して、所望のバージョンが表示されればインストールは完了です。

```
$ git clone https://github.com/hyperledger/caliper-benchmarks.git
$ cd caliper-benchmarks
$ git checkout v0.3.0
$ npm init -y
$ npm install --only=prod @hyperledger/caliper-cli@0.3.0
$ $ npx caliper --version
v0.3.0
```

## 基本的な使い方

ここではFabricを例に説明していきます。まず、事前準備として使用するSDKのバージョンを宣言します。例えば、以下の通りです。

```
$ npx caliper bind --caliper-bind-sut fabric:1.4.1
```

続いて、今回のサンプル実行に必要な証明書類を生成します。Fabric固有のステップなので基盤によっては必要ありません。また、使用するサンプルネットワークによって実行場所は``config_solo_raft``などとなります。

```
$ cd caliper-benchmarks/networks/fabric/config_solo
$ ./generate.sh
```

原因不明ですが、以下のようなエラーが出た場合は``mychannel.tx``を一旦削除して再度``generate.sh``を実行すると上手くいきました。

```
Error on outputChannelCreateTx: Error writing channel create tx: open mychannel.tx: is a directory
```

実際に実行します。以前のCaliperからオプション名こそ若干変わったものの指定するパラメータはほとんど変わっていません。複数クライアントマシンを使用するケースに備えて master / worker を指定するようなっていますが、単一クライアントの場合は気にせずmasterを指定しておけば大丈夫です。

```
$ npx caliper launch master \\
  --caliper-workspace <ワークスペースディレクトリのパス> \\
  --caliper-benchconfig <ベンチマーク構成ファイルのワークスペースからの相対パス> \\
  --caliper-networkconfig <ネットワーク構成ファイルのワークスペースからの相対パス>
```

ベンチマーク構成ファイルでは、どういうワークロードでどれくらいの負荷をかけるかを指定し、ネットワーク構成ファイルでは評価対象のブロックチェーンネットワークを指定します。``caliper-benchmarks``リポジトリ内の``benchmarks``ディレクトリ、``networks``ディレクトリのそれぞれにサンプルファイルがあります。具体的な実行例は以下の通りです。

```
$ npx caliper launch master \\
  --caliper-workspace . \\
  --caliper-benchconfig benchmarks/scenario/smallbank/config.yaml \\
  --caliper-networkconfig networks/fabric/fabric-v1.4.1/2org1peergoleveldb/fabric-go.yaml
```

ネットワーク構成ファイルでは開始終了時に実行するコマンドを指定できるようになっており、各サンプルでは、そこでdocker-composeを使用して評価対象のブロックチェーンネットワークを起動するようになっています。

実行が終わると、下記のようなHTML形式のレポートが出力され、スループットやレイテンシ、リソースの使用状況などを確認することができます。

<img width="1228" alt="caliper_report.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465166/1dd56df4-aed4-5cfe-646f-6afe7baec422.png">
[Hyperledger Caliperのレポートサンプル](caliper_report.png)

## 複数クライアントホストでの使い方

v0.3.0では同一ホストにおける複数クライアントプロセスだけでなく、複数ホスト上に分散した複数クライアントで負荷をかけることができます。

少々手間ですが、MQTTブローカーを立てておく必要があります。今回は[このあたり](https://qiita.com/hilucky/items/42492e7ef5706b718bbb)を参考にCaliperを実行するホストと同一のホスト上に立てました。

複数ホストの場合、まず、以下のようにmasterを起動します。事前に準備したMQTTブローカーとポート番号を指定するのがポイントです。

```
$ npx caliper launch master \\
  --caliper-workspace /path/to/caliper-benchmarks \\
  --caliper-benchconfig benchmarks/scenario/smallbank/config.yaml \\
  --caliper-networkconfig networks/scalardl/scalardl_smallbank.json \\
  --caliper-worker-remote true \\
  --caliper-worker-communication-method mqtt \\
  --caliper-worker-communication-address mqtt://localhost:1883
```

次に、workerを起動します。ワークスペースは異なっていても問題ありませんが、複数ホストであっても同じ構成にしておくのが良さそうです。

```
$ npx caliper launch worker \\
  --caliper-workspace /path/to/caliper-benchmarks \\
  --caliper-benchconfig benchmarks/scenario/smallbank/config.yaml \\
  --caliper-networkconfig networks/scalardl/scalardl_smallbank.json \\
  --caliper-worker-remote true \\
  --caliper-worker-communication-method mqtt \\
  --caliper-worker-communication-address mqtt://localhost:1883
```

workerを起動すると、MQTTブローカー経由でmasterと通信が行われ、ベンチマーク構成ファイルにおける``workers.number``で指定したworker数が揃った段階でテストが開始されます。

## TIPS

**一部処理のみ実行**

サンプルネットワークで実行する際は、上記の方法で、ネットワークの構築、コントラクトのインストール、テストの実行、後片付けまで一括して行ってくれて便利ですが、実環境の場合、特定のフェーズだけを行いたいという場合が多々あると思います。

その場合、実行時に``--caliper-flow-only-test``といったオプションを指定すると特定のフェーズだけを実行することもできます。ネットワーク構築(start)、初期化(init)、コントラクトのインストール(install)、実行(test)、ネットワーク後片付け(end)があります。onlyのかわりにskipを指定すると、特定のフェーズだけ飛ばすこともできます。詳細は[こちら](https://hyperledger.github.io/caliper/v0.3/runtime-config/#benchmark-phase-settings)。

## ベンチマーク構成ファイルで指定可能な項目

- ``workers``
  - ``type`` : 現在、このパラメータは無視されるようです。
  - ``number`` : 負荷をかけるworkerの数を指定します。単一クライアントで実行する場合、指定した数のwokerプロセスが起動します。複数クライアントで実行する場合、masterはここで指定した数のworkerが参加してくるまで待ちます。

- ``rateControl``
  - ``fixed-rate`` : 指定されたレート(tps)でトランザクションを送信します。
  - ``fixed-feedback-rate`` : 未完了のトランザクションがある場合に、一時的にトランザクションの送信を止めながら、指定されたレートで実行します。
  - ``fixed-backlog`` : 初期負荷を決めて、積み残しを一定に保ちつつ負荷を変化させます。

- ``callback`` : ワークロード(アプリケーション)の処理が記述されたJavaScriptファイルを指定します。(例: 口座開設、残高照会)

- ``monitor`` : モニタリング対象のDockerコンテナなどを指定します。

パラメータの詳細は[こちら](https://hyperledger.github.io/caliper/v0.3/bench-config/)を参照してください。

## サンプルで用意されているワークロード

``caliper-benchmarks/benchmarks/scenario``ディレクトリにサンプルのワークロードがあります。現在は、simple、smallbankのみです。``benchmarks/{api,samples}``にもFabric専用と思われるものがいくつかのサンプルがあるようですが、動作確認はしていません。

ワークロード名   | 概要
---------------|----------------------------------------------------------------
simple         | 単純なGet/Putを行うワークロード。
smallbank      | 口座開設、預入れ、送金などを模したワークロード。

## 嵌まりポイント

サンプルのネットワーク構成にFabric v2.0.0があるので試したくなるのですが、FabricのSDKがv2.0.0向けにチャネル管理機能をサポートしていないらしく、地道に環境を作った後でonly-testで流してね、とのことです。

https://github.com/hyperledger/caliper/issues/810