Corda Enterprise Performance 検証

TIS Blockchain Promotion Office
15 min readAug 21, 2020

Corda JMeterの使い方

■はじめに

システムを導入する際、一般的にはパフォーマンステストの実施が必要です。ブロックチェーンは新しい技術であり、パフォーマンステスト用ツールが充実していない部分もありますが、Corda Enterpriseには「Corda JMeter」が用意されており、Cordaに特化したパフォーマンステストの実施が可能です。今回は記事を2回に分けてCorda JMeterの使い方と、我々のほうで実施したノードスペックを変化することによる性能変化をご紹介します。

今回、第1回目はCorda JMeterの使い方について紹介します。

■開発環境

・ Windows10

・ IntelliJ

・ Kotlin 1.2 / Java 1.8

■実行環境

・ Corda Enterprise 4.3(2020年8月時点では最新版は4.5)

・ Corda JMeter 4.2 ・・・Cordaの処理に特化したJMeter。Enterpriseのモジュールに含まれています。レポート出力に一部不備があったため、Apache JMeter 5.2.1も併用

・ AWS EC2・・・インスタンスタイプは、パフォーマンステストケースに応じて変更。Cordaのノード、ノード用のDBは同一サーバに相乗りさせます。

・ PostgreSQL 9.6

・Corda側ノード環境・・・NodeA、NodeB、Notaryの3台構成(CENMはNotaryノードと相乗り)

・Corda側で利用する Flow(ソースコードは最下部の付録に記載)

-Create:自ノードに対して発行を実施する。Notaryは関与しない。

-Send:他ノードに送信する。Notaryが関与する。

・JMeter側設定・・・同時(0秒)に100スレッド作成し、10回ループする

- スレッド数:100

-Ramp-up:0

-ループ回数:10

■Corda JMeter設定方法

ポイントをおさえ、設定方法・使用方法を紹介していきます。

▼モジュール取得

  1. モジュール配置用のフォルダ(A)を作成します。
  2. Apache JMeterをこちらからダウンロードし、解凍後、Aに配置します。
  3. Corda Enterprise のモジュールから「jmeter-corda-X.Y-capsule.jar」をJMeterのbinフォルダ下に配置します。( X.Yはバージョンを表す)
  4. CordaのGithub(こちら)より、Samplerを取得し、Aに配置します。
  5. 自身で作成されたCordappを、Aに配置します。
フォルダ構成のイメージ

▼Samplerの修正

Cordappの依存関係を解決するため、修正が必要になります。また、実行するFlowに合わせて、Samplerの修正や新規作成を行う必要があります。

1.jmeter-samplerフォルダに「lib」フォルダを新規作成し、Cordappのjarを配置します。

jmeter-samplerにlibを配置

2.build.gradle の dependencies で、配置したjarを読み込むように指定します。

dependencies {
ext.jmeterVersion = "3.3"
ext.cordaVersion = "4.3"
ext.cordaOsVersion = "4.3"
compile files("lib/workflows.jar","lib/contracts.jar")

3.Samplerの修正/新規作成をします。(今回利用したソースコード全量は最下部の付録に記載)

【Samplerの修正ポイント】

a.パラメータを定義する・・・JMeterProperties に、JMeterで使用するパラメータを定義する。

companion object JMeterProperties {     // JMeterのパラメータで使用する変数を定義 
val tokenId = Argument("tokenID","","<meta>","tokenID")
val type = Argument("Type","","<meta>","type")
val value = Argument("value","0","<meta>","value")
}

b.パラメータの値を取得する・・・setupTestでパラメータ名と値を取得する。

override fun setupTest(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext) {
   // パラメータから値を受け取る
// パラメータ名(XXX.name)と値(XXX.value)
// 値が文字列以外の場合は、toXXX()で変換をかける
   tID = testContext.getParameter(tokenId.name,tokenId.value)!!
typ = testContext.getParameter(type.name,type.value)!!
vlu = testContext.getParameter(value.name,value.value)!!.toInt()
}

c.パラメータを使用可能にする・・・additionalArgsでパラメータを指定する。

override val additionalArgs: Set<Argument> 
  // ここで指定(setOf)した変数がGUI上でパラメータとして設定できるようになる
get() = setOf(tokenId, type, value)

d.Flowを使用可能にする。

override fun createFlowInvoke(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext): FlowInvoke<*> {
// 実行するFlow(のクラス)を指定する
// 第2引数には、実行するFlowの引数を配列で渡す
  // tokenID,Type,value
return FlowInvoke<TokenCreateFlow.Initiator>(TokenCreateFlow.Initiator::class.java, arrayOf(tID,typ,vlu))
}
↑↑returnで改行されているように見えますが、Medium記事の表現上の理由によるものです。実際には return FlowInvokeのように改行なし、スペースですのでご注意ください

▼SamplerJarの作成

前述した修正点を反映したjarファイルを作成します。

gradlew.bat jar

build/libsにSNAPSHOT.jarが作成されます。

custom-sampler-1.0-SNAPSHOT.jarの作成

▼Corda JMeter GUI 起動

実際にノードに対してトランザクションを投げるため、事前にCorda Nodeを起動しておきます。

Corda JMeter を起動しますが、引数(XadditionalSearchPaths)に、上記のSNAPSHOT.jarとFlowのjarを指定する必要があります。

SNAPSHOT.jarを指定しないと後述のクラス指定が行えず、Flowのjarを指定しないとエラー(ClassNotFoundException)が発生します。

Corda JMeter のjarファイルがあるフォルダに移動し、Corda JMeterを起動します。(各jarはフルパスを指定。区切りは;(セミコロン)環境によりパスは適宜変更してください。)

cd ApacheJMeter/bin
java -jar jmeter-corda-4.2-capsule.jar -XadditionalSearchPaths=/A/jmeter-sampler/build/libs/custom-sampler-1.0-SNAPSHOT.jar;/A/jmeter-sampler/lib/workflows.jar

▼テスト計画の作成

基本的な使い方は、Apache JMeterと同じですが、Javaリクエストで任意のFlowを呼び出せることが相違点です。

1.テスト計画(右クリック)>追加>Threads>スレッドグループを選択します。

2.スレッドグループ(右クリック)>追加>サンプラー>Javaリクエストを選択します。

3.クラス名のプルダウンから対象のクラスを選択します。

4.パラメータを設定します。実際のパラメータはnode.confを参照して設定してください。

Javaリクエストのパラメータ設定

なお、ノードを指定する場合は、略称ではなく、PartyFullNameを指定してください。

例)

誤:PartyB

正:O=PartyB,L=New York,C=US

ノード指定時はPartyFullNameを指定

パラメータの名前が意図したものが表示されていない場合、Sampler側で適切に実装されていない可能性があります。JMeterPropertiesで定義した変数を、additionalArgsでパラメータとして指定してください。

override val additionalArgs: Set<Argument>
// ここで指定(setOf)した変数がGUI上でパラメータとして設定できるようになる
get() = setOf(tokenId, otherParty, value)

5.実行結果用のリスナー設定をします。(CLI実行のみであれば不要)

6.スレッドグループを選択し、スレッド数やループの回数といったプロパティを設定します。

- スレッド数:100

-Ramp-up:0

-ループ回数:10

尚、CordaはJavaベースということもあり、初回アクセスの反応が悪いため、下図のような試運転用のスレッドグループも作成しています。

試運転用のスレッドグループ設定

7.スレッドグループではなく、「テスト計画」を保存してください。拡張子は「jmx」です。

「テスト計画」を選択し右クリック、別名で保存
テスト計画を保存

8.下図の▶をクリックすることでテストが実行されます。なお、GUIで実行すると、表示等にメモリを消費する為、性能を正しく測定する場合は、CLIから実行することが推奨されています。

テストの実行

■実行方法

両Flowを別のテスト計画として実施しています。また、前述の通り、適切に性能検証を行うためコマンドライン(CLI)で実施しています。

テストの進め方としては、テスト実行→インスタンス停止→インスタンスタイプ変更→インスタンス起動→テスト実行→・・・のように実施していきました。

▼Corda JMeter の実行

実行するFlowの説明と、実行方法は以下の通りです。Corda JMeter GUIを起動したコマンドにオプションを追加しています。

● -n・・・Non-GUI-Mode

● -t・・・テスト計画のjmxファイルを指定します。(相対パスでも可)

● -l・・・レポート出力用のjtlファイル名を指定します。出力先に同名のファイルがある場合は出力できません。

1.Create

NodeAがCreateのFlowを実行

java -jar jmeter-corda-4.2-capsule.jar -XadditionalSearchPaths=/A/jmeter-sampler/build/libs/custom-sampler-1.0-SNAPSHOT.jar;/A/jmeter-sampler/lib/workflows.jar -- -n -t create.jmx -l 001_create.jtl

2.Send

NodeAがNodeBに向けてSendのFlowを実行

java -jar jmeter-corda-4.2-capsule.jar -XadditionalSearchPaths=/A/jmeter-sampler/build/libs/custom-sampler-1.0-SNAPSHOT.jar;/A/jmeter-sampler/lib/workflows.jar -- -n -t send.jmx -l 002_send.jtl

▼レポートHTML出力

Apache JMeterであれば、上記のコマンド実行の際にオプションをつけることで、そのままレポート出力が可能ですが、Corda JMeterだとうまく出力されなかったため、Apache JMeterを使用してレポートを出力します。使用するオプションは以下の通りです。

● -g・・・レポート出力対象のjtlファイルを指定します。(相対パスでも可)

● -o・・・レポート出力先のフォルダを指定します。(相対パスでも可)このときフォルダは空でなければいけません。

1.Createのレポート出力

jmeter -g 001_create.jtl -o 001_create_test_h2db_report

2.Sendのレポート出力

jmeter -g 002_send.jtl -o 002_send_test_h2db_report

▼レポート確認

テスト計画が正常に完了した場合、指定したフォルダにいくつかのフォルダやファイルが出力されています。そのうちの「index.html」をブラウザで開くことで、グラフィカルにレポートを参照することができます。

レポート出力後
index.html

以上が実施までの手順です。

今回、JMeter初心者ということもあり、実施するまでに、多少の時間がかかってしまいました。手順内に記載しておりますが、改めて以下のポイントを注意していれば比較的早く実施できると思います。

■注意するポイント

1.JMeterでノードの指定方法

略称ではなく、PartyFullNameを指定する。
誤:PartyB
正:O=PartyB,L=New York,C=US

2.JMeterでクラス名に表示されない(Flowが実行対象に無い)時の対処方法

JMeterを起動する時に「-XadditionalSearchPaths」で、対象となるSamplerのjarを指定する必要がある。また、Samplerが別ディレクトリのCordapp jarを参照している場合は、そのjarも含める必要がある。

3.JMeterで名前に表示されない(パラメータとして存在しない)時の対処方法

Samplerで「JMeterProperties」でパラメータを定義して、「additionalArgs」でパラメータを登録する

4.JMeter起動時にjarを指定する

上記の通りFlowのjarと、Samplerのjarを指定する必要がある。

5.レポート(html)出力がされない時の対処方法

Corda JMeter だと出力されない。こちら側の設定ミスの可能性も考えられるが、対処法として実行結果ファイル(jtl)をCorda JMeterで作成し、そのファイルをApache JMeterで読み込ませてレポートを出力する。

上記ポイントをおさえれば、Corda JMeterでの実行はできると思います。

次回はこのCorda JMeterを使い、サーバスペックを変化させることで性能にどのように影響が出るかを見ていきます。

記:TIS Blockchain Promotion Office (Yamasaki)

Thanks to Nobuhiro Yokoyama and Hideki Nakachi.

■付録

CreateFlow.kt

SendFlow.kt

example-sampler

example-sampler_send.kt

--

--