![よっしー](https://yossi-note.com/wp-content/themes/cocoon-master/images/man.png)
こんにちは。よっしーです(^^)
今日は、k6を利用した大規模なテスト実行におけるOSの設定についてご紹介します。
背景
Dockerで構築したWebアプリの開発環境において、k6を利用した負荷テストについて調査したときの内容を備忘として残しました。
開発環境のソースは下記のリポジトリにあります。
ローカルポートの範囲
アウトバウンドネットワーク接続を作成する際、カーネルは利用可能なポートの範囲から接続のためのローカル(ソース)ポートを割り当てます。
GNU/Linux
GNU/Linuxでは、この範囲を次のコマンドで確認できます:
sysctl net.ipv4.ip_local_port_range net.ipv4.ip_local_port_range = 32768 60999
28,231のポートはほとんどのユースケースには十分かもしれませんが、数千の接続をテストする場合には制限要因となる可能性があります。例えば、次のようにして増やすことができます:
sysctl -w net.ipv4.ip_local_port_range="16384 65000"
これはTCPとUDPの両方に適用されることに注意し、選択する値を慎重に選び、必要に応じて増やしてください。
変更を永続的にするには、net.ipv4.ip_local_port_range=16384 65000を/etc/sysctl.confに追加します。最後の手段の調整 上記の変更でまだネットワークの問題が発生する場合、net.ipv4.tcp_tw_reuseを有効にすることを検討してみてください:
sysctl -w net.ipv4.tcp_tw_reuse=1
これにより、TIME_WAIT状態の接続を迅速に再利用する機能が有効になり、より高いスループットが得られる可能性があります。
macOS/Linux
macOSでは、デフォルトのエフェメラルポート範囲は49152から65535までの16384ポートです。これはsysctlコマンドで確認できます:
sysctl net.inet.ip.portrange.first net.inet.ip.portrange.last
net.inet.ip.portrange.first: 49152
net.inet.ip.portrange.last: 65535
通常、エフェメラルポートが枯渇すると、特定のポート番号を再利用できるまでTIME_WAIT状態が期限切れ(最大セグメント寿命の2倍)になるまで待つ必要があります。ポートの数を倍にするには、範囲を32768で開始するように変更できます。これはLinuxとSolarisのデフォルトです(最大ポート番号は65535なので、高い方を増やすことはできません)。
sudo sysctl -w net.inet.ip.portrange.first=32768
net.inet.ip.portrange.first: 49152 -> 32768
IANAが指定した公式の範囲は49152から65535であり、一部のファイアウォールは動的に割り当てられたポートがこの範囲内にあると仮定することがあります。ローカルネットワークの外側でより大きな範囲を使用するようにファイアウォールを再構成する必要があるかもしれません。
一般的な最適化について
このセクションでは、OSに依存しないいくつかの最適化について説明しますが、これらはテストに影響を与える可能性があります。
RAMの使用
特定のk6テストによって、最大のVU数、JavaScriptの依存関係の数とサイズ、テストスクリプトの複雑さに応じて、k6はテスト実行中にシステムRAMの大量消費を引き起こすことがあります。開発はRAMの使用をできるだけ削減することに焦点を当てていますが、特定のシナリオでは1回のテスト実行で数十ギガバイトのRAMを使用することがあります。
ベースラインとして、各VUインスタンスは、スクリプトの複雑さと依存関係に応じて1MBから5MBのRAMを必要とすると考えてください。たとえば、1,000のVUを使用するテストでは、1GBから5GBのシステムRAMが必要となる場合があるため、テスト要件を満たすために十分な物理RAMが利用可能であることを確認してください。
RAMの使用を減少させる必要がある場合、オプション–compatibility-mode=baseを使用できます。JavaScript互換モードについての詳細は、JavaScript互換性モードに関する記事を参照してください。
仮想メモリ
物理RAMに加えて、より高いメモリ使用が必要な場合に備えて、システムに適切な仮想メモリまたはスワップスペースの量が設定されていることを確認してください。
システムの利用可能なスワップスペースの状態と量は、swaponまたはfreeといったコマンドで確認できます。
ここではスワップの設定詳細については説明しませんが、オンラインでいくつかのガイドを見つけることができます。
ネットワークの性能
k6は大量のネットワークトラフィックを生成し、維持できるため、現代のオペレーティングシステムのネットワークスタックに負荷をかけます。特定の負荷またはネットワーク条件下では、オペレーティングシステムのネットワーク設定を微調整したり、テストのネットワーク条件を再構築することで、スループットを向上させ、パフォーマンスを向上させることができる場合があります。
TCP TIME_WAIT期間
TCPネットワークアプリケーション、例えばウェブクライアントやサーバーは、各着信または送信接続ごとにネットワークソケットペア(ローカルアドレス、ローカルポート、リモートアドレス、リモートポートの一意の組み合わせ)が割り当てられます。通常、このソケットペアは単一のHTTPリクエスト/レスポンスセッションに使用され、すぐに閉じられます。しかし、アプリケーションによって接続が正常に閉じられた後でも、新しい一致するTCPセグメントが到着した場合に同じソケットを迅速に再オープンするためにカーネルはリソースを予約する可能性があります。これは、一部のパケットが伝送中に失われるネットワークの混雑時にも発生します。これにより、ソケットはTIME_WAIT状態になり、TIME_WAIT期間が切れるとリリースされます。この期間は通常15秒から2分の間で構成されています。
k6などの一部のアプリケーションが直面する問題は、多数の接続がTIME_WAIT状態になり、新しいネットワーク接続の作成を防ぐ可能性があることです。
このようなシナリオでは、他のアプリケーションに有害な副作用をもたらすかもしれないシステムネットワーク構成を変更する前に、まず一般的なテストの注意を払うことが望ましいです。異なるサーバーポートまたはIPを使用する
ソケットは通常、ローカルアドレス、ローカルポート、リモートアドレス、リモートポートの組み合わせに対して一意に作成されるため、TIME_WAITの混雑を回避するための安全なワークアラウンドは、異なるサーバーポートまたはIPアドレスを使用することです。
例えば、アプリケーションをポート:8080、:8081、:8082などで実行し、これらのエンドポイントにHTTPリクエストを分散させることができます。
おわりに
今日は、k6を利用した大規模なテスト実行におけるOSの設定についてご紹介しました。
![よっしー](https://yossi-note.com/wp-content/themes/cocoon-master/images/man.png)
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント