vegeta は HTTP 負荷テストツールで、Go で書かれており、コマンドラインインターフェースを使用し、結果分析のために要約とグラフを生成できます。
基本使用#
詳細な使用方法は README の内容を参照してください。コマンドラインインターフェースと Go プログラムにライブラリとして組み込む 2 つの方法で使用できます。私は brew を使って vegeta をインストールし、テストプロセス全体は Go でスクリプトを作成して行いました。具体的にはコードスニペットを参照してください。
私はライブラリの形式で組み込むのではなく、exec.Command()関数を使用してコマンドラインを実行しました。
具体的に使用する vegeta コマンド
- attack: API を呼び出すコマンドで、rate は毎秒の呼び出し回数、duration は呼び出し秒数、body は POST リクエストのリクエストボディ、name はこのテストに名前を付けるためのもので「省略可能」、tee は bin の生ファイルを生成します「生の画像フォーマットのようなもので、bin を使って他の多くのフォーマットに変換できます」、report はレポートを生成し、ここではコマンドラインに出力されます。
echo "POST http://172.17.1.36:30898/hello" | vegeta attack -rate=2000 -duration=1s -body=query.json -timeout=0 -name=hello | tee ./result/results-null.bin | vegeta report
- レポートファイルを生成します。ここでは bin の生ファイルから txt ファイルを生成します。
vegeta report -type=text results-query.bin > repost.txt
- 分析グラフを生成します。plot を使用するとインタラクティブなグラフを生成できます。複数の結果を 1 つのグラフに統合する必要がある場合、最初のコマンドを使用する際には必ず - name パラメータを追加して名前を付けてください。
vegeta plot results-null.bin results-sleep.bin results-query.bin > plot-all.html
テストシナリオ#
Java と Go で 2 つの REST サービスを作成し、それぞれ 3 つの API をテストします。k8s での単一レプリカと 5 レプリカの状況です。API 情報は以下の通りです:
- 直接返す
- 2 秒待ってから返す
- Elasticsearch から 10000 件のデータを取得し、各データは 500 バイト
Elasticsearch クラスター情報
- ノード数:2
- バージョン:7.4.1
- CPU:8 つの Intel (R) Xeon (R) Silver 4114 CPU @ 2.20GHz、各 1 コア
- メモリ:31G
Kubernetes 情報
- バージョン:1.16.15
- ノード数:7「1 master, 6 worker」
Deployment を同じノードにスケジュールし、2 つの Deployment に 2G のメモリを割り当てました。
テスト手順#
Go スクリプトをパッケージ化した後、同じディレクトリに設定ファイルconfig.iniを作成します。
[address]
null = "POST http://172.17.1.36:30898/hello"
sleep = "POST http://172.17.1.36:30898/sleep"
query = "POST http://172.17.1.36:30898/es"
[param]
rate = 2000
ここで address は呼び出す API のアドレスとメソッドを指し、rate は毎秒の呼び出し回数を指します「ここでは 1 秒間だけ呼び出しました」。
スクリプトを実行し、待機……
テスト結果#
各 API は 3 つのファイルを生成しました。
- results-*.bin ファイル:テストの生ファイル
- report-*.txt ファイル:レポートファイル
- plot-*.html ファイル:単一結果のグラフファイル
まずは Java
- 空のインターフェース
Requests [total, rate, throughput] 2000, 2004.21, 1996.25
Duration [total, attack, wait] 1.002s, 997.9ms, 3.98ms
Latencies [min, mean, 50, 90, 95, 99, max] 2.114ms, 28.492ms, 11.283ms, 77.584ms, 90.305ms, 111.482ms, 150.836ms
Bytes In [total, mean] 10000, 5.00
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:2000
フィールドの説明
Requests(リクエスト数):
- total は総リクエスト数を示し、ここでは 2000 です。
- rate は毎秒発信されるリクエスト数を示し、ここでは 2004.21 です。
- throughput は毎秒成功したリクエスト数を示し、ここでは 1996.25 です。
Duration(持続時間):
- total はテストの総時間を示し、ここでは 1.002 秒です。
- attack は攻撃時間、つまり実際にリクエストを送信した時間を示し、ここでは 997.9 ミリ秒です。
- wait は攻撃中のすべてのリクエストの総待機時間を示し、ここでは 3.98 ミリ秒です。
Latencies(応答時間):
- min は最小応答時間を示します。
- mean は平均応答時間を示します。
- 50, 90, 95, 99 は分位数「この指標が何を示しているのかあまり理解していません」、それぞれ 50%、90%、95%、99% の応答時間を示します。
- max は最大応答時間を示します。
Bytes In(受信バイト数):
- total はすべてのリクエストの総受信バイト数を示します。
- mean は各リクエストの平均受信バイト数を示します。
Bytes Out(送信バイト数):
- total はすべてのリクエストの総送信バイト数を示します。
- mean は各リクエストの平均送信バイト数を示します。
Success(成功率):
- ratio は成功したリクエストの総リクエストに対する割合を示します。
Status Codes(ステータスコード):
- codeは各ステータスコードの出現回数を示します。
3 つの結果を統合したとき、応答時間は基本的に線形に増加し、クエリ時間は最終的に 3 分を超えました。
- Go
sleep と空のインターフェースは非常に安定しており、クエリインターフェースの応答時間も Java よりはるかに良好です。
次に、2 つのサービスを 5 つのレプリカに追加した後の結果です。
- Java
sleep インターフェースの安定性が向上し、線形に増加することはありませんが、クエリインターフェースの応答時間は依然として少し異常です。
- Go
クエリインターフェースの応答時間にはあまり改善が見られません。
まとめ#
クエリインターフェースに関しては、ボトルネックが Elasticsearch 側にある可能性があり、ここではテストを行いません。
グラフから見ると、Go の並行処理能力は確かにわずかに優れています。
vegeta というツールにはまだ多くの使い方があり、Jmeter に比べてコマンドラインはあまり親切ではありませんが、生成される結果は非常に直感的です。