ラボでサーバーのベンチマークを行い、実際のトラフィックに展開したところ、ベンチマークのパフォーマンスに近いものがまったく得られなかったという経験はありませんか? CPU 使用率は低く、空きリソースは豊富にあるのに、クライアントは応答時間が遅いと不満を言い、サーバーからより効率的に使用できるようにする方法がわかりません。
あなたが観察しているのは、「HTTP の重い処理」と呼べるものの 1 つの効果です。 このブログ記事では、HTTP がどのように動作し、一般的な HTTP サーバーが HTTP トランザクションをどのように処理するかを調査します。 発生する可能性のあるパフォーマンスの問題のいくつかを確認し、NGINX のイベント駆動型モデルがこれらの HTTP サーバーにとって非常に効果的な高速プロキシになる仕組みを確認します。 NGINX を使用すると、実際のパフォーマンスを変換して、ローカル ベンチマークのレベルに戻すことができます。
Linux と NGINX をチューニングしてアプリケーションの速度とスケーラビリティを向上させるためのヒントについては、弊社のブログの「パフォーマンス向上のための NGINX のチューニング」をご覧ください。
HTTP キープアライブ接続は、待ち時間を減らし、Web ページの読み込みを高速化するために必要なパフォーマンス機能です。
HTTP はシンプルなテキストベースのプロトコルです。 これまで行っていない場合は、Web ブラウザーなどの HTTP デバッグ ツールからの出力を確認し、標準的なリクエストと応答の構造を確認してください。
最も単純な実装では、HTTP クライアントが宛先サーバーへの新しい TCP 接続を作成し、要求を書き込んで、応答を受信します。 その後、サーバーは TCP 接続を閉じてリソースを解放します。
この動作モードは、特に多数の要素を含む複雑な Web ページの場合や、ネットワーク リンクが遅い場合には、非常に非効率的になる可能性があります。 新しい TCP 接続を作成するには「3 ウェイ ハンドシェイク」が必要であり、接続を解除するには双方向のシャットダウン手順も必要です。 メッセージごとに TCP 接続を繰り返し作成して閉じることは、電話での会話で各人が話した後に電話を切ってリダイヤルすることに似ています。
HTTP は、HTTP トランザクションが完了した後もクライアントとサーバー間の TCP 接続を開いたままにするために、キープアライブ接続と呼ばれるメカニズムを使用します。 クライアントが別の HTTP トランザクションを実行する必要がある場合、新しい TCP 接続を作成するのではなく、アイドル キープアライブ接続を使用できます。
クライアントは通常、サーバーに対して複数の同時 TCP 接続を開き、それらすべてにわたってキープアライブ トランザクションを実行します。 これらの接続は、通常はアイドル タイムアウトの結果として、クライアントまたはサーバーが不要であると判断するまで開いたままになります。
最近の Web ブラウザは通常、6 ~ 8 個のキープアライブ接続を開き、タイムアウトするまで数分間開いたままにします。 Web サーバーは、これらの接続をタイムアウトにして、より早く閉じるように構成できます。
多数のクライアントが HTTP キープアライブを使用し、Web サーバーに同時実行の制限またはスケーラビリティの問題がある場合、その制限に達するとパフォーマンスが急激に低下します。
上記のアプローチは、個々のクライアントに可能な限り最高のパフォーマンスを提供するように設計されています。 残念ながら、「コモンズの悲劇」のようなシナリオでは、すべてのクライアントがこのように動作すると、多くの一般的な Web サーバーと Web アプリケーションのパフォーマンスに悪影響を与える可能性があります。
その理由は、多くのサーバーでは同時実行数の制限が固定されているからです。 たとえば、一般的な構成では、Apache HTTP Server は限られた数の同時 TCP 接続しか処理できません。 ワーカーマルチプロセッシング モジュール (MPM) では 150、プリフォークMPM では 256。 アイドル状態の HTTP キープアライブ接続ごとに、これらの同時実行スロットの 1 つが消費され、すべてのスロットが占有されると、サーバーはそれ以上の HTTP 接続を受け入れることができなくなります。
一般的な考え方では、Web サーバー上のキープアライブをオフにするか、キープアライブの有効期間を非常に短く制限することが推奨されています。 これらは、 SlowHTTPTestおよびSlowlorisサービス拒否攻撃の非常に単純なベクトルを提供します (簡単な解決策については、serverfault.com の「Protecting against Keep‑Dead Denial of service 」を参照してください)。
さらに、これらの Web サーバーとアプリケーション サーバーは通常、接続ごとにオペレーティング システムのスレッドまたはプロセスを割り当てます。 TCP 接続は非常に軽量なオペレーティング システム オブジェクトですが、スレッドまたはプロセスは非常に重量があります。 スレッドとプロセスにはメモリが必要であり、オペレーティング システムによってアクティブに管理される必要があり、スレッドまたはプロセス間の「コンテキスト切り替え」によって CPU が消費されます。 各接続に独自のスレッドまたはプロセスを割り当てることは非常に非効率的です。
多数の同時クライアント接続と各接続へのスレッドまたはプロセスの割り当てにより、「HTTP ヘビー リフティング」と呼ばれる現象が発生し、軽量の HTTP トランザクションを処理するために不釣り合いに大きな労力が必要になります。
現代の多くの Web サーバーやアプリケーション サーバーでは、同時実行の制限を使い果たすのに多くのクライアントは必要ありません。
クライアントが 8 つの TCP 接続を開き、各接続を最後に使用してから 15 秒間維持する場合、クライアントは 15 秒間 8 つの同時実行スロットを消費します。 クライアントが 1 秒あたり 1 台の割合で Web サイトにアクセスする場合、120 個の同時実行スロットがアイドル キープアライブ接続によって継続的に占有されます。 レートが 1 秒あたり 2 クライアントの場合、240 の同時実行スロットが占有されます。 スロットが使い果たされると、既存の接続がタイムアウトするまで新しいクライアントは接続できません。
これにより、サービスのレベルが非常に不均一になる可能性があります。 キープアライブ接続を正常に取得したクライアントは、自由にサービスを参照できます。 同時実行スロットがすべて占有されているときに接続を試みるクライアントはロックアウトされ、キューで待機する必要があります。
これらの問題は、クライアント数が多く、ネットワークが遅い場合にのみ発生します。 高速ローカル ネットワーク上の単一のクライアントでベンチマークを実行する場合には表示されません。
ベンチマークでこれらの効果が見られない理由はいくつかあります。
ほとんどのベンチマーク ツールは成功したトランザクションのみを報告することに注意してください。 リソース不足のために停止した接続は報告されない場合があり、成功した接続のごく一部としてのみ報告される場合もあります。 これにより、現実世界の交通における問題の本質が隠されてしまいます。
スレッドベースまたはプロセスベースの Web サーバーやアプリケーション サーバーは、同時実行の制限に対して脆弱です。
この問題は、各接続にスレッドまたはプロセスを割り当てるすべての Web またはアプリケーション プラットフォームに固有のものです。 最適化されたベンチマーク環境では検出が容易ではありませんが、実際の環境ではパフォーマンスの低下や CPU 使用率の過剰として現れます。
この問題に対処するには、いくつかの対策があります。
NGINX は、上記の同時実行性の問題が発生しない異なるアーキテクチャを使用します。 低速のクライアント接続を最適化されたベンチマークのような接続に変換し、サーバーから最高のパフォーマンスを引き出します。
NGINX は、非常に効率的なイベント駆動型モデルを使用して接続を管理します。
各 NGINX プロセスは複数の接続を同時に処理できます。 新しい接続が受け入れられると、上記のプロセスごとまたはスレッドごとのモデルとは異なり、オーバーヘッドは非常に低くなります (新しいファイル記述子とポーリングする新しいイベントで構成されます)。 NGINX には非常に効果的なイベント ループがあります。
これにより、各 NGINX プロセスは、同時に数十、数千、または数十万の接続に簡単に拡張できます。
次に、NGINX は、キープアライブ接続のローカル プールを使用して、リクエストをアップストリーム サーバーにプロキシします。 TCP 接続を開いたり閉じたりすることによるオーバーヘッドは発生せず、TCP スタックは最適なウィンドウ サイズと再試行パラメータに迅速に適応します。 要求の書き込みと応答の読み取りは、ローカルの最適化されたネットワーク上ではるかに高速になります。
最終的な効果は、アップストリーム サーバーが高速ネットワークを介して単一のローカル クライアント (NGINX) と通信することになり、クライアントは HTTP キープアライブ接続を最適に利用して、接続を不必要に開いたままにすることなく接続のセットアップを最小限に抑えることになります。 これにより、サーバーはベンチマークのような最適な環境に戻ります。
NGINX が HTTP プロキシとして機能する場合、次のようになります。
HTTP の負荷を軽減することは、過負荷のアプリケーション インフラストラクチャに対して NGINX が実現できるパフォーマンス変革策の 1 つにすぎません。
NGINX のHTTP キャッシュ機能は、標準のキャッシュ セマンティクスに従って、キャッシュされる内容と期間を制御することで、アップストリーム サーバーからの応答をキャッシュできます。 複数のクライアントが同じリソースを要求した場合、NGINX はキャッシュから応答し、重複した要求でアップストリーム サーバーに負担をかけません。
NGINX は、アップストリーム サーバーから他の操作をオフロードすることもできます。 データ圧縮操作をオフロードして帯域幅の使用量を削減し、 SSL/TLS 暗号化と復号化を一元管理し、初期クライアント認証 ( HTTP 基本認証、外部認証サーバーへのサブリクエスト、 JSON Web トークンなど) を実行し、必要に応じてあらゆる種類のルールを適用してトラフィックをレート制限することができます。
最後に、他の高速プロキシ、ロードバランサ、またはアプリケーション配信コントローラ (ADC) とは異なり、NGINX は完全な Web サーバーでもあることを忘れないでください。 NGINX を使用すると、静的コンテンツを提供したり、Java、PHP、Python、Ruby などの言語のアプリケーション サーバーにトラフィックを転送したり、メディア (オーディオとビデオ) を配信したり、認証およびセキュリティ システムと統合したり、NGINX 構成に埋め込まれたルールを使用してトランザクションに直接応答したりすることもできます。
パフォーマンスの制限が組み込まれていないため、NGINX と NGINX Plus は、現在および将来にわたって、導入先のハードウェアを最大限に活用できます。
NGINX Plus を試すには、今すぐ30 日間の無料トライアルを開始するか、お問い合わせの上、使用事例についてご相談ください。
「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"