Scaling前書きこのガイドでは、NginxのHTTPプロキシ機能について説明します。これにより、NginxはリクエストをバックエンドHTTPサーバーに渡してさらに処理することができます。Nginxは、インフラストラクチャのスケールアウトを支援したり、大きなクライアント負荷を処理するように設計されていない他のサーバーに要求を渡すために、リバースプロキシソリューションとしてセットアップされることがよくあります。途中で、Nginxの組み込みの負荷分散機能を使用してスケールアウトする方法について説明します。クライアントのプロキシ操作のパフォーマンスを向上させるために、バッファリングとキャッシングを検討します。単純な単一サーバー構成で過去にWebサーバーのみを使用したことがある場合、リクエストをプロキシする必要があるのか​​疑問に思うかもしれません。Nginxから他のサーバーにプロキシする理由の1つは、インフラストラクチャをスケールアウトする機能です。Nginxは、多くの同時接続を同時に処理するように構築されています。これにより、クライアントの窓口として理想的です。サーバーは、任意の数のバックエンドサーバーにリクエストを渡して、大量の作業を処理し、インフラストラクチャ全体に負荷を分散できます。この設計により、メンテナンスのために必要に応じてバックエンドサーバーを簡単に追加したり停止したりする柔軟性が得られます。HTTPプロキシが役立つもう1つの例は、実稼働環境のクライアントからの要求を直接処理するように構築されていないアプリケーションサーバーを使用する場合です。多くのフレームワークにはWebサーバーが含まれていますが、それらのほとんどはNginxのような高パフォーマンス用に設計されたサーバーほど堅牢ではありません。Nginxをこれらのサーバーの前に配置すると、ユーザーのエクスペリエンスが向上し、セキュリティが向上します。Nginxでのプロキシは、Nginxサーバーを対象としたリクエストを操作し、実際の処理のために他のサーバーに渡すことで実現されます。リクエストの結果はNginxに返され、Nginxは情報をクライアントに中継します。このインスタンスの他のサーバーは、リモートマシン、ローカルサーバー、またはNginx内で定義された他の仮想サーバーです。Nginxがリクエストをプロキシするサーバーは、「アップストリームサーバー」と呼ばれます。Nginxは、http(s)、FastCGI、SCGI、uwsgi、またはmemcachedプロトコルを使用して通信するサーバーに、プロキシの種類ごとに個別のディレクティブセットを介してリクエストをプロキシできます。このガイドでは、httpプロトコルに焦点を当てます。Nginxインスタンスは、リクエストを渡し、アップストリームサーバーが理解できる形式にメッセージコンポーネントをマッサージします。単純なタイプのプロキシには、httpを使用して通信できる単一のサーバーに要求を渡すことが含まれます。+`ディレクティブによって処理されます。`ディレクティブは主にロケーションコンテキストにあります。`コンテキストでも有効です。+`ディレクティブを持つ場所と一致すると、リクエストはディレクティブによって指定されたURLに転送されます。+`定義のサーバーの最後にURIは指定されていません。このパターンに適合する定義の場合、クライアントから要求されたURIはそのままアップストリームサーバーに渡されます。`サーバーに送信されます。代替シナリオを見てみましょう。+`定義で指定されている場合、_location_定義に一致するリクエストの部分は、パス中にこのURIに置き換えられます。http://example.com/new/prefix/please+」としてアップストリームサーバーに渡されます。+`に置き換えられます。これは覚えておくべき重要なポイントです。時々、この種の交換は不可能です。+`定義の最後のURIは無視され、クライアントからの元のURIまたは他のディレクティブによって変更されたURIが上流サーバーに渡されます。正規表現を使用して場所が一致する場合、NginxはURIのどの部分が式に一致したかを判断できないため、元のクライアント要求URIを送信します。別の例は、同じ場所で書き換えディレクティブが使用され、クライアントURIが書き換えられるが、同じブロックで処理される場合です。この場合、書き換えられたURIが渡されます。Nginxがヘッダーを処理する方法を理解するすぐには明らかにならないかもしれないことの1つは、アップストリームサーバーが要求を適切に処理することを期待している場合、URI以外のものを渡すことが重要であることです。クライアントに代わってNginxから送信されるリクエストは、クライアントから直接送信されるリクエストとは異なります。これの大部分は、リクエストに付随するヘッダーです。Nginxがリクエストをプロキシするとき、クライアントから受信するリクエストヘッダーを自動的に調整します。Nginxは空のヘッダーを取り除きます。空の値を別のサーバーに渡す意味はありません。リクエストを膨らませるためだけに役立ちます。Nginxは、デフォルトで、アンダースコアを含むヘッダーを無効と見なします。プロキシされたリクエストからこれらを削除します。+`ディレクティブを「on」に設定できます。しないと、ヘッダーがバックエンドサーバーに到達しません。`変数で定義された値に書き換えられます。+`ディレクティブで直接定義されます。「接続」ヘッダーが「閉じる」に変更されます。このヘッダーは、2つのパーティ間で確立された特定の接続に関する情報を通知するために使用されます。この例では、Nginxはこれを「close」に設定して、元の要求に応答するとこの接続が閉じられることを上流サーバーに示します。アップストリームは、この接続が永続的であることを期待すべきではありません。上記から推測できる最初のポイントは、渡したくない_ヘッダーは空の文字列に設定する必要があるということです。空の値を持つヘッダーは、渡されたリクエストから完全に削除されます。上記の情報から収集する次のポイントは、バックエンドアプリケーションが非標準ヘッダーを処理する場合、アンダースコアが「ない」ことを確認する必要があるということです。これを行わないと、Nginxはこれらのヘッダーに無効のフラグを付け、アップストリームに渡す前に静かにドロップします。「Host」ヘッダーは、ほとんどのプロキシシナリオで特に重要です。`の値に設定されます。+`定義から直接取得したドメイン名またはIPアドレスとポートを含む変数です。これは、Nginxがアップストリームサーバーが確実に応答できる唯一のアドレスであるため、デフォルトで選択されています(接続情報から直接取得されるため)。「Host」ヘッダーの最も一般的な値は次のとおりです。+」定義から取得したドメイン名またはIPアドレスとポートコンボに「Host」ヘッダーを設定します。これはデフォルトであり、Nginxの観点からは「安全」ですが、通常、プロキシされたサーバーが要求を正しく処理するために必要なものではありません。+:「Host」ヘッダーをクライアント要求からの「Host」ヘッダーに設定します。クライアントから送信されたヘッダーは、変数としてNginxで常に利用可能です。`で始まり、その後に小文字のヘッダー名が続き、ダッシュはアンダースコアに置き換えられます。+`変数はほとんどの場合機能しますが、クライアントリクエストに有効な「Host」ヘッダーがない場合、パスが失敗する可能性があります。+:この変数は、優先順位に従って設定されます:リクエスト行自体からのホスト名、クライアントリクエストからの「ホスト」ヘッダー、またはリクエストに一致するサーバー名。+」変数に設定します。これは最も柔軟性があり、通常、プロキシされたサーバーに可能な限り正確に入力された「ホスト」ヘッダーを提供します。+`ディレクティブを使用できます。前述のように「Host」ヘッダーを変更し、プロキシされたリクエストに共通するヘッダーを追加するには、次のようなものを使用できます。この変数には、リクエストされている元のホストに関する情報が含まれている必要があります。+`ヘッダーは、プロキシされたサーバーに元のクライアントリクエストのスキーマに関する情報を提供します(httpまたはhttpsリクエストであったかどうか)。`はクライアントのIPアドレスに設定されるため、プロキシはこの情報に基づいて正しく判断したりログを記録したりできます。X-Forwarded-For`ヘッダーは、クライアントがこの時点までプロキシされたすべてのサーバーのIPアドレスを含むリストです。X-Forwarded-For`ヘッダーの値を取り、NginxサーバーのIPアドレスを最後に追加します。+`ディレクティブをサーバーまたはhttpコンテキストに移動して、複数の場所で参照できるようにすることもできます。前の例では、単一のバックエンドサーバーに対して単純なHTTPプロキシを実行する方法を示しました。Nginxでは、リクエストを渡すことができるバックエンドサーバーのプール全体を指定することで、この構成を簡単にスケールアウトできます。`ディレクティブを使用してサーバーのプールを定義します。この構成では、リストされているサーバーのいずれかがクライアントの要求を処理できることを前提としています。これにより、ほとんど労力をかけずにインフラストラクチャを拡張できます。+`ディレクティブは、Nginx設定のhttpコンテキストで設定する必要があります。」と呼ばれるアップストリームコンテキストを設定しました。定義すると、この名前は通常のドメイン名であるかのようにプロキシパス内で使用できるようになります。/...​+`に対して行われたリクエストを上記で定義したプールに渡します。そのプール内で、構成可能なアルゴリズムを適用してホストが選択されます。デフォルトでは、これは単なる単純なラウンドロビン選択プロセスです(各リクエストは順番に異なるホストにルーティングされます)。アップストリームバランシングアルゴリズムの変更アップストリームコンテキスト内にディレクティブまたはフラグを含めることにより、アップストリームプールで使用されるバランシングアルゴリズムを変更できます。(ラウンドロビン):他のバランシングディレクティブが存在しない場合に使用されるデフォルトのロードバランシングアルゴリズム。アップストリームコンテキストで定義された各サーバーには、リクエストが順番に渡されます。*:アクティブな接続の数が最も少ないバックエンドに常に新しい接続を与えることを指定します。これは、バックエンドへの接続がしばらく続く場合に特に便利です。*:このバランシングアルゴリズムは、クライアントのIPアドレスに基づいて異なるサーバーにリクエストを分散します。最初の3オクテットは、要求を処理するサーバーを決定するためのキーとして使用されます。その結果、クライアントは毎回同じサーバーからサービスを受ける傾向があり、セッションの一貫性を保つことができます。*:このバランスアルゴリズムは、主にmemcachedプロキシで使用されます。サーバーは、任意に提供されたハッシュキーの値に基づいて分割されます。これは、テキスト、変数、または組み合わせにすることができます。これは、ユーザーがデータを提供する必要がある唯一のバランス調整方法であり、ハッシュに使用する必要があるキーです。バランシングアルゴリズムを変更すると、ブロックは次のようになります。.上記の例では、接続が最も少ないサーバーに基づいてサーバーが選択されます。+`ディレクティブを同じ方法で設定して、一定量のセッション「スティッキネス」を取得できます。+`メソッドに関しては、ハッシュするキーを提供する必要があります。これは何でも構いません。.上記の例では、クライアントのIPアドレスとポートの値に基づいてリクエストを分散します。これは、ketamaの一貫したハッシュアルゴリズムを実装しています。基本的に、これは、アップストリームサーバーが変更されても、キャッシュへの影響が最小限であることを意味します。バランシングのためのサーバーの重みの設定バックエンドサーバーの宣言では、デフォルトで、各サーバーは等しく「重み付け」されます。これは、各サーバーが同じ量の負荷を処理できることを想定しています(負荷分散アルゴリズムの影響を考慮して)。宣言中にサーバーに代替の重みを設定することもできます。+`は他の2つのサーバーの3倍のトラフィックを受け取ります。デフォルトでは、各サーバーに1の重みが割り当てられます。バッファを使用してバックエンドサーバーを解放する多くのユーザーに関係するプロキシの問題の1つは、プロセスにサーバーを追加した場合のパフォーマンスへの影響です。ほとんどの場合、これはNginxのバッファリングおよびキャッシング機能を利用することで大幅に軽減できます。別のサーバーにプロキシする場合、2つの異なる接続の速度がクライアントのエクスペリエンスに影響します。クライアントからNginxプロキシへの接続。Nginxプロキシからバックエンドサーバーへの接続。Nginxには、最適化するこれらの接続のいずれかに基づいて動作を調整する機能があります。バッファなしでは、プロキシされたサーバーからデータが送信され、すぐにクライアントへの送信が開始されます。クライアントが高速であると想定される場合、できるだけ早くクライアントにデータを取得するために、バッファリングをオフにすることができます。バッファーを使用すると、Nginxプロキシはバックエンドの応答を一時的に保存し、このデータをクライアントにフィードします。クライアントが遅い場合、これによりNginxサーバーはより早くバックエンドへの接続を閉じることができます。その後、可能なペースでクライアントにデータを配信できます。クライアントは接続速度が大きく異なる傾向があるため、Nginxはデフォルトでバッファリング設計になっています。次のディレクティブを使用して、バッファリング動作を調整できます。これらは、http、サーバー、または場所のコンテキストで設定できます。サイジングディレクティブは_request_ごとに設定されるため、必要以上に大きくすると、多くのクライアントリクエストがある場合にパフォーマンスに影響を与えることに注意することが重要です。*:このディレクティブは、このコンテキストと子コンテキストのバッファリングを有効にするかどうかを制御します。デフォルトでは、これは「オン」です。*:このディレクティブは、プロキシされる応答のバッファーの数(最初の引数)とサイズ(2番目の引数)を制御します。+`のいずれか)に等しいサイズの8つのバッファーを構成します。バッファーの数を増やすと、より多くの情報をバッファーできます。*:ヘッダーを含むバックエンドサーバーからの応答の最初の部分は、残りの応答とは別にバッファリングされます。このディレクティブは、応答のこの部分のバッファーのサイズを設定します。+`と同じサイズになりますが、これはヘッダー情報に使用されるため、通常はより小さな値に設定できます。*:このディレクティブは、「client-ready」とマークされてビジーになることができるバッファーの最大サイズを設定します。クライアントは一度に1つのバッファからしかデータを読み取ることができませんが、バッファはキューに配置されて、クライアントにまとめて送信されます。このディレクティブは、この状態にできるバッファスペースのサイズを制御します。*:これは、ディスク上の一時ファイルのリクエストごとの最大サイズです。これらは、アップストリームの応答が大きすぎてバッファに収まらない場合に作成されます。*:これは、プロキシされたサーバーの応答が設定されたバッファーに対して大きすぎる場合に、Nginxが一時ファイルに一度に書き込むデータの量です。*:これは、上流サーバーからの応答が設定されたバッファーに収まらない場合にNginxが一時ファイルを保存するディスク上の領域へのパスです。ご覧のとおり、Nginxはバッファリング動作を微調整するための非常に多くの異なるディレクティブを提供しています。ほとんどの場合、これらの大部分について心配する必要はありませんが、これらの値の一部を調整すると便利です。+`ディレクティブです。各アップストリームリクエストで使用可能なプロキシバッファーの数を増やし、ヘッダーを格納する可能性のあるバッファーを削減する例は次のようになります。http://example.com;}対照的に、すぐにデータを提供したい高速クライアントがある場合は、バッファリングを完全にオフにすることができます。アップストリームがクライアントより速い場合、Nginxは実際にバッファを実際に使用しますが、バッファがプールされるのを待つのではなく、すぐにクライアントにデータをフラッシュしようとします。クライアントが遅い場合、クライアントが追いつくまでアップストリーム接続が開いたままになる可能性があります。http://example.com;}高可用性(オプション)Nginxプロキシは、ロードバランサーの冗長セットを追加して高可用性インフラストラクチャを作成することにより、より堅牢にできます。高可用性(HA)セットアップは、単一障害点のないインフラストラクチャであり、ロードバランサーはこの構成の一部です。複数のロードバランサーを使用することにより、ロードバランサーが利用できない場合や、メンテナンスのためにロードバランサーを停止する必要がある場合に、潜在的なダウンタイムを防ぎます。基本的な高可用性セットアップの図を次に示します。[HAセットアップ]この例では、1つのサーバーから別のサーバーに再マップできる静的IPアドレスの背後に、複数のロードバランサー(1つはアクティブで、1つ以上はパッシブ)があります。クライアント要求は、静的IPからアクティブなロードバランサーにルーティングされ、その後バックエンドサーバーにルーティングされます。ToのこのセクションフローティングIPを使用する]。応答時間を短縮するためのプロキシキャッシングの構成バッファリングはより多くのリクエストを処理するためにバックエンドサーバーを解放するのに役立ちますが、Nginxはバックエンドサーバーからコンテンツをキャッシュする方法も提供し、多くのリクエストに対してアップストリームに接続する必要性を排除します。`ディレクティブを使用できます。これにより、プロキシされたサーバーから返されたデータを保持できる領域が作成されます。+`ディレクティブはhttpコンテキストで設定する必要があります。以下の例では、これといくつかの関連するディレクティブを構成して、キャッシュシステムをセットアップします。`ディレクティブで、キャッシュを保存したいファイルシステム上のディレクトリを定義しました。+`ディレクトリを選択しました。このディレクトリが存在しない場合は、次のように入力して、正しい許可と所有権で作成できます。+`パラメーターは、キャッシュの編成方法を指定します。Nginxは、キーの値をハッシュすることによりキャッシュキーを作成します(以下で設定)。上記で選択したレベルは、2文字のサブディレクトリ(ハッシュ値の末尾から次の2文字から取得)を持つ1文字のディレクトリ(これがハッシュ値の最後の文字になります)が作成されることを示しています。通常、これの詳細を気にする必要はありませんが、Nginxが関連する値をすばやく見つけるのに役立ちます。`パラメータは、このキャッシュゾーンの名前を定義します。これは、保存するメタデータの量を定義する場所でもあります。MBのキーを保存しています。Nginxは、メガバイトごとに約8000エントリを保存できます。+`パラメータは、実際にキャッシュされるデータの最大サイズを設定します。これは、キャッシュされた値を保存するために使用されるキーを設定するために使用されます。この同じキーを使用して、キャッシュからリクエストを処理できるかどうかを確認します。これをスキーム(httpまたはhttps)、HTTP要求メソッド、および要求されたホストとURIの組み合わせに設定しています。+`ディレクティブは複数回指定できます。これにより、ステータスコードに応じて値を保存する期間を設定できます。この例では、成功とリダイレクトを10分間保存し、毎分404応答のキャッシュを期限切れにします。キャッシュゾーンを構成しましたが、キャッシュを使用するタイミングをNginxに伝える必要があります。バックエンドにプロキシする場所で、このキャッシュの使用を構成できます。+`キャッシュゾーンを使用するように指定できます。Nginxは、バックエンドに渡す前に有効なエントリをここで確認します。+`変数に設定されます。これには、クライアントが新しい非キャッシュバージョンのリソースを明示的に要求しているかどうかに関するインジケータが含まれます。このディレクティブを設定すると、Nginxはこれらのタイプのクライアントリクエストを正しく処理できます。これ以上の構成は必要ありません。X-Proxy-Cache」という追加のヘッダーを追加しました。+`変数の値に設定します。基本的に、これにより、リクエストによってキャッシュヒット、キャッシュミス、またはキャッシュが明示的にバイパスされたかどうかを確認できるヘッダーが設定されます。これは特にデバッグに役立ちますが、クライアントにとっても有益な情報です。キャッシュ結果に関する注意キャッシュを使用すると、プロキシのパフォーマンスを大幅に改善できます。キャッシュを構成する際には、留意すべき考慮事項が必ずあります。ユーザー関連のデータをキャッシュしないでください。これにより、あるユーザーのデータが別のユーザーに表示される可能性があります。サイトが完全に静的である場合、これはおそらく問題ではありません。サイトに動的な要素がある場合は、バックエンドサーバーでこれを考慮する必要があります。これをどのように処理するかは、バックエンド処理を処理しているアプリケーションまたはサーバーによって異なります。"に設定する必要があります。*:バックエンドでデータが変更されていないことを最初に確認せずに、応答を再度提供しないことを示します。これは、データが動的で重要な場合に使用できます。ETagハッシュメタデータヘッダーは各リクエストでチェックされ、バックエンドが同じハッシュ値を返す場合、以前の値を提供できます。*:受信したデータをキャッシュするべきではないことを示します。これは、データを毎回サーバーから取得する必要があることを意味するため、プライベートデータの最も安全なオプションです。*:これは、このデータをキャッシュする共有キャッシュスペースがないことを示します。これは、ユーザーのブラウザがデータをキャッシュできることを示すのに役立ちますが、プロキシサーバーはこのデータを後続のリクエストで有効と見なすべきではありません。*:これは、応答が接続の任意の時点でキャッシュできるパブリックデータであることを示します。これは、リソースをキャッシュする秒数を示します。コンテンツの機密性に応じてこれらのヘッダーを正しく設定すると、プライベートデータの安全性と動的データの新鮮さを保ちながら、キャッシュを活用できます。`ディレクティブを使用してこれの一部を設定できます。-1;}上記の例では、最初のブロックにより、コンテンツを1時間キャッシュできます。Cache-Control」ヘッダーを「no-cache」に設定します。+`ディレクティブを使用できます。"no-store";}結論Nginxは何よりもまずリバースプロキシであり、たまたまWebサーバーとして機能することもあります。この設計上の決定により、他のサーバーへのリクエストのプロキシはかなり簡単です。Nginxは非常に柔軟性があり、必要に応じてプロキシ設定をより複雑に制御できます。