こんにちは。よっしーです(^^)
今日は、k6を利用した大規模なテスト実行についてご紹介します。
背景
Dockerで構築したWebアプリの開発環境において、k6を利用した負荷テストについて調査したときの内容を備忘として残しました。
開発環境のソースは下記のリポジトリにあります。
背景
k6は、単一のマシンから多くの負荷を生成することができます。適切なモニタリングとスクリプトの最適化を行えば、分散実行を必要とせずにかなり大規模な負荷テストを実行できるかもしれません。この記事では、そのようなテストの実行方法と、注意すべき側面について説明します。
マシンが生成する負荷を最大限に活用するには、以下の要素が含まれる多面的なプロセスが必要です:
- デフォルトのネットワークおよびユーザーリミットを増やすために、オペレーティングシステムの設定を変更する。
- ロードジェネレーターマシンをモニタリングして、適切なリソースの使用を確認する。
- スクリプト、k6のオプション、およびファイルのアップロードに注意を払い、効率的なテストを設計する。
- k6によって記録されたエラーを監視し、これらのエラーはロードジェネレーターマシンまたは対象システム(SUT)の制限を示す可能性があることに注意する。
単一のk6プロセスは、ロードジェネレーターマシン上のすべてのCPUコアを効率的に使用します。利用可能なリソースに応じて、この記事で説明されているガイドラインに従って、単一のk6インスタンスで30,000〜40,000の同時ユーザー(VU)を実行できます。一部のケースでは、この数のVUが秒間最大300,000のHTTPリクエストを生成することができます。
100,000〜300,000リクエスト/秒(1分あたり6-12百万リクエスト)以上の必要がない限り、単一のk6インスタンスはおそらくあなたのニーズに十分でしょう。単一のマシンから最大の負荷を得る方法について詳しく学ぶために、続けて読んでください。
OSの調整
現代のオペレーティングシステムは、アプリケーションが作成できる同時ネットワーク接続数の制限が比較的低い設定で構成されています。これは、ほとんどのプログラムがk6のように数千の同時TCP接続を開く必要がないため、安全なデフォルト設定です。ただし、ネットワーク容量を最大限に活用し、最大のパフォーマンスを実現したい場合は、これらのデフォルト設定の一部を変更する必要があります。
GNU/Linuxマシンで、ルートユーザーとして次のコマンドを実行します:
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_timestamps=1
ulimit -n 250000
これらのコマンドは、ネットワーク接続の再利用を有効にし、ネットワーク接続の制限とローカルポートの範囲を増加させます。
sysctlコマンドは、すぐにシステム全体に適用され、ネットワークサービスを再起動するかマシンを再起動するとデフォルト値にリセットされます。ulimitコマンドは現在のシェルセッションにのみ適用され、別のシェルインスタンスでそれを設定するには再度実行する必要があります。
これらの設定の詳細情報、これらを永続的に設定する方法、およびmacOS用の指示については、別途、記事を作成予定になります。
ハードウェアの考慮事項
負荷が増加するにつれて、ハードウェアの制約に注意する必要があります。
ネットワーク
大規模なテストを実行する際には、マシンのネットワークスループットも重要な考慮事項です。多くのAWS EC2マシンは1Gbit/sの接続を備えており、これはk6が生成できる負荷を制限する可能性があります。 テストを実行する際には、ターミナル内でiftopのようなツールを使用して、リアルタイムで生成されるネットワークトラフィックの量を表示します。トラフィックが1Gbit/sで一定の場合、テストはおそらくネットワークカードに制限されている可能性があります。異なるEC2インスタンスにアップグレードを検討してみてください。
CPU
k6は非常にマルチスレッドであり、利用可能なすべてのCPUコアを効果的に活用します。 必要なCPUの量は、テストスクリプトと関連ファイルに依存します。テストファイルに関係なく、大規模なテストにはかなりのCPUパワーが必要です。我々は、マシンに少なくとも20%のアイドルサイクル(k6によって80%使用、20%アイドル)を持つようにサイジングすることをお勧めします。k6がCPUの100%を使用して負荷を生成する場合、テストは制限され、これにより結果のメトリクスが実際よりもはるかに大きな応答時間を持つ可能性があります。
メモリ
k6は、他のいくつかの負荷テストツールよりも効率的にメモリを使用できますが、多くのメモリを使用することがあります。メモリ消費量は、テストシナリオに大きく依存します。テストのメモリ要件を見積もるには、開発マシンで100のVUを使用してテストを実行し、消費されるメモリを目標のVU数で乗算します。 単純なテストでは、1つのVUあたり約1〜5MBを使用します(1000のVU=1〜5GB)。ファイルのアップロードを行うテストや大きなJSモジュールを読み込むテストは、1つのVUあたり数十メガバイトを消費することがあります。各VUはテストで使用するすべてのJSモジュールのコピーを持っていることに注意してください。VU間でメモリを共有するには、SharedArrayやRedisなどの外部データストアを考慮してください。 スワップ領域を使用している場合は、無効にすることを検討してください。物理メモリが不足すると、メモリを非常に遅いセカンダリストレージにスワップするプロセスがパフォーマンスとシステムの安定性に乱れを生じる可能性があります。これはテストの異なる部分でロードジェネレーターのパフォーマンスが異なるため、テスト結果が無効になる可能性があります。代わりに、テストで期待されるメモリ使用量を事前に計画し、使用量が90%を超えないように十分な物理RAMを確保してください。
ロードジェネレーターのモニタリング
前のセクションでは、ハードウェアがマシンが生成できる負荷を制限する方法について説明しました。これを念頭に置いて、特にテストを初めて実行する場合は、テストが実行されている間にリソースをモニタリングすることが重要です。
ロードジェネレーターをモニタリングする最も簡単な方法は、マシン上で複数のターミナルを開くことです。k6を実行するための1つのターミナルと、CPU、メモリ、およびネットワークをモニタリングするための他のターミナルを開きます。以下のツールをお勧めします:
- CPUとメモリ:htopまたはnmon。
- ネットワーク:iftopまたはnmon。
グラフィカルなアプリケーションを好む場合は、OSのシステムモニタリングツール(例:GNOME System MonitorまたはPlasma System Monitor)や、SysMonTaskのようなスタンドアロンツールを使用してください。
以下は、k6、iftop、およびhtopを表示する3つのターミナルセッションのスクリーンショットの例です。
モニタリングのガイドライン
テストが実行されている間、以下はモニタリングすべき良い指標です:
- CPU利用率が80%以内に収まっていること:テスト実行中にすべてのCPUコアが100%利用されると、テスト結果のパフォーマンスの低下が見られる可能性があります。
- ネットワーク利用率が適切なレベルにあること:テストに応じて、ネットワーク帯域幅を完全に活用することを期待するか、テストが利用可能な帯域幅に制約されていることを示すかもしれません。他のシナリオでは、コストを抑えるためにネットワーク使用を最小限に抑えたい場合もあります。
- メモリ使用率が90%を超えないこと:利用可能な物理RAMが枯渇しそうな場合、システムはメモリをディスクにスワップし始め、パフォーマンスとシステムの安定性に影響を与えます(スワップ領域の完全な無効化をお勧めしています)。極端な場合、Linuxでメモリが不足すると、システムがk6プロセスを終了させる可能性があります。
おわりに
今日は、k6を利用した大規模なテスト実行についてご紹介しました。
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント