目標
現状のmijin Catapult F5でどの程度の性能があるか検証する。
テストは定番のJmeterを使用してmijinに負荷テストを実施する。
安定してmijinが稼働できる指標を目指す。
※ 瞬間的な最大トランザクション承認数の調査ではない
(1ブロック6000txが捌けることは確認しているため)
構成
- Jmeterネットワーク
- mijinネットワーク
mijin構成
ネットワーク及びインスタンスなどの基盤構築はCloudformationで行い、mijinはansibleで構築
- ALB(ELB) x 1(SSL化や入れ替え用)
- APIノード x 1
- PEERノード x 2
APIノード
mongoがある分、PEERノードよりメモリを多くしている
項目 | 値 |
---|---|
スペック | m5.large(2CPU 8GB) |
mongo disk | EBS disk(io1 1000IOPS) |
block disk | EBS disk(io1 300IOPS) |
PEERノード
項目 | 値 |
---|---|
スペック | c5.large(2CPU 4GB) |
block disk | EBS disk(io1 300IOPS) |
mijin設定
主な変更点のみ
rest.json
Throttlingの設定をし、上限を超えない程度に制限する。
"throttling": {
"burst": 120,
"rate": 100
},
Defaultだと設定がなく 5
で制限されている。
制限を緩和しないと以下のようなエラーがでてしまう。
0
にすると無制限にできるが、mijin側でエラーが多発するためおすすめしない。
{"statusCode":429,"errorDetails":{"statusCode":429,"statusMessage":"Too Many Requests"},"body":{"code":"TooManyRequests","message":"You have exceeded your request rate of 5 r/s."}}
config-network.properties
5秒でブロック生成する。(Default 15s)
この値はnemsis block作成時から変更は不可なので変更する場合は、最初からmijinを作り直す必要あり
blockGenerationTargetTime = 5s
docker-composeのmongo設定
mongoはメモリを多く消費するため、wiredTigerCacheSizeGBにて制限をかけておく
services:
db:
image: mongo:4.2.5
command: bash -c "mongod --dbpath=/dbdata --bind_ip=db --wiredTigerCacheSizeGB 3.0"
テスト内容
事前に用意したMosaicをランダムで作成したアドレスにTransferTransactionで送信する。
抜粋すると以下のような方法で作成
// 適用なデータを作成
const hash = CryptoJS.SHA512(Crypto.randomBytes(5).toString());
const hashConvert = Convert.hexToUint8(hash.toString(CryptoJS.enc.Hex));
// 署名
const hashSig = KeyPair.sign(keyPair, hashConvert);
// プライベートキーを作成
const toPrivateKey = Convert.uint8ToHex(hashSig.slice(0, 32));
const toAccount = Account.createFromPrivateKey(toPrivateKey, networktype);
// トランザクションを作成するための内容を作る
const transferTransaction = TransferTransaction.create(
Deadline.create(23), // 23時間
toAccount.address,
[new Mosaic( new MosaicId(mosaicId), UInt64.fromUint(1))],
PlainMessage.create('Stees Test Count' + count),
networktype
).setMaxFee(100);
// 作成したトランザクションに署名する
const signedTransaction = account.sign(transferTransaction, ghash);
// signedTransaction.payload をjmeterで使用する
テスト実行方法
Jmeter Masterからjmxファイルを実行し、jmeter Slaveをリモート実行する。
構成では記載していないが、トランザクションデータはpayloadに変換し、redisに格納されている。
(redisデータを毎回取りに行くオーバヘッドはあるが、いちいちトランザクションファイルを作成すると時間がかかるのでBeanShellでredisから値を取得するようにして無限ループできるようにしている)
$ /opt/apache-jmeter-5.2.1/bin/jmeter -n -t ./jmeter_stress_test_redis.jmx -r \
-Gthrednum=1 \ スレッド数1
-Grampup=1 \
-Gredis_host=redis.mijin.internal \
-Gredis_key=transfer \
-Gredis_cmd=/usr/bin/redis-cli \
-Gloop=-1 // 無限ループ
実行結果
3時間で200万トランザクションを投げ、25%ほどエラーになった。
このエラーは、上記でも記載したとおり、 throttling
の制限によりトランザクションを受け付けれなかったエラーとなる。
summary = 2003403 in 03:01:09 = 184.3/s Avg: 2 Min: 0 Max: 473 Err: 517193 (25.82%)
infra@master-srv:~$ /opt/apache-jmeter-5.2.1/bin/jmeter -n -t /home/infra/jmeter_stress_test_redis.jmx -r -l test/log_${DATE}.csv -Gthrednum=1 -Grampup=1 -Gredis_host=redis.mijin.internal -Gredis_key=transfer -Gredis_cmd=/usr/bin/redis-cli -Gloop=-1
Creating summariser <summary>
Created the tree successfully using /home/infra/jmeter_stress_test_redis.jmx
Configuring remote engine: 172.17.2.212:1099
Configuring remote engine: 172.17.2.70:1099
Starting distributed test with remote engines: [172.17.2.70:1099, 172.17.2.212:1099] @ Tue Apr 14 12:10:19 JST 2020 (1586833819480)
Warning: Nashorn engine is planned to be removed from a future JDK release
Remote engines have been started:[172.17.2.70:1099, 172.17.2.212:1099]
Waiting for possible Shutdown/StopTestNow/HeapDump/ThreadDump message on port 4445
summary + 1003 in 00:00:09 = 109.9/s Avg: 4 Min: 1 Max: 180 Err: 0 (0.00%) Active: 2 Started: 2 Finished: 0
summary + 5400 in 00:00:30 = 177.8/s Avg: 3 Min: 0 Max: 25 Err: 58 (1.07%) Active: 2 Started: 2 Finished: 0
summary = 6403 in 00:00:40 = 162.1/s Avg: 3 Min: 0 Max: 180 Err: 58 (0.91%)
summary + 5100 in 00:00:30 = 170.6/s Avg: 3 Min: 0 Max: 65 Err: 284 (5.57%) Active: 2 Started: 2 Finished: 0
summary = 11503 in 00:01:09 = 165.8/s Avg: 3 Min: 0 Max: 180 Err: 342 (2.97%)
~~~~~~ 省略 ~~~~~~~~~~~~~~~~~~
summary + 5500 in 00:00:30 = 183.7/s Avg: 3 Min: 0 Max: 22 Err: 589 (10.71%) Active: 2 Started: 2 Finished: 0
summary = 1976803 in 02:58:39 = 184.4/s Avg: 2 Min: 0 Max: 473 Err: 510585 (25.83%)
summary + 5400 in 00:00:31 = 176.4/s Avg: 3 Min: 0 Max: 70 Err: 529 (9.80%) Active: 2 Started: 2 Finished: 0
summary = 1982203 in 02:59:10 = 184.4/s Avg: 2 Min: 0 Max: 473 Err: 511114 (25.79%)
summary + 5900 in 00:00:30 = 199.6/s Avg: 2 Min: 0 Max: 45 Err: 1353 (22.93%) Active: 2 Started: 2 Finished: 0
summary = 1988103 in 02:59:39 = 184.4/s Avg: 2 Min: 0 Max: 473 Err: 512467 (25.78%)
summary + 5900 in 00:00:30 = 197.0/s Avg: 1 Min: 0 Max: 91 Err: 2057 (34.86%) Active: 2 Started: 2 Finished: 0
summary = 1994003 in 03:00:09 = 184.5/s Avg: 2 Min: 0 Max: 473 Err: 514524 (25.80%)
summary + 5100 in 00:00:30 = 170.8/s Avg: 3 Min: 0 Max: 22 Err: 1417 (27.78%) Active: 2 Started: 2 Finished: 0
summary = 1999103 in 03:00:39 = 184.4/s Avg: 2 Min: 0 Max: 473 Err: 515941 (25.81%)
summary + 4300 in 00:00:30 = 141.5/s Avg: 5 Min: 5 Max: 69 Err: 1252 (29.12%) Active: 2 Started: 2 Finished: 0
summary = 2003403 in 03:01:09 = 184.3/s Avg: 2 Min: 0 Max: 473 Err: 517193 (25.82%)
負荷の状況
負荷の状況はCloudwatchにてモニタリングしている。
CPU使用率も安定し、ディスクのIOPSも制限以下で遷移した。
Dropping Transaction Countは catapult_serverxxxx.log
をCloudwatch Logsに送信し、メトリクスフィルタでdropしたトランザクションを集計している。
Reject Error Countは catapult_brokerxxxx.log
をCloudwatch Logsに送信し、メトリクスフィルタでbrokerがrejectしたトランザクションを集計している。
上記2つのカウントが上昇した場合、ほぼトランザクションが滞留し、ブロック生成に遅延が発生及びトランザクションが破棄されている。
考察
結果を考えると、今回のスペックでは 大体 136tx/s
を連続してトランザクションを発行しても安定して稼働できると考える。(少なからず3時間は)
ただ、長時間続くとキャッシュがたまり、 Failure_Chain_Unconfirmed_Cache_Too_Full
がでて、トランザクションがrejectされる可能性もあるので、今回程度の最低推奨スペック程度ではなく、もう少しスペックを上げて調査したい。
summary = 2003403 in 03:01:09 = 184.3/s Avg: 2 Min: 0 Max: 473 Err: 517193 (25.82%)
テスト数 2,003,403トランザクション
負荷時間 03:01:09
平均処理 184tx/s
最小レスポンス時間 2 (ms)
最大レスポンス時間 473 (ms)
エラーテスト数 517193 (25.82%
—————————————————————
成功平均処理 184 * 0.7418 ≒ 136tx/s(TPS)