Nginx HTTPプロキシ、負荷分散、バッファリング、キャッシュについて

前書き

このガイドでは、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プロキシパスの分解

最も単純なタイプのプロキシには、httpを使用して通信できる単一のサーバーに要求を渡すことが含まれます。 このタイプのプロキシは一般的な「プロキシパス」と呼ばれ、適切な名前の `+ proxy_pass +`ディレクティブによって処理されます。

`+ proxy_pass `ディレクティブは主にロケーションコンテキストにあります。 また、ロケーションコンテキスト内の ` if `ブロックおよび ` limit_except `コンテキストでも有効です。 リクエストが内部に ` proxy_pass +`ディレクティブを持つ場所と一致すると、リクエストはディレクティブによって指定されたURLに転送されます。

例を見てみましょう。

# server context

location /match/here {
   proxy_pass http://example.com;
}

. . .

上記の設定スニペットでは、 `+ proxy_pass +`定義のサーバーの最後にURIは指定されていません。 このパターンに適合する定義の場合、クライアントから要求されたURIはそのままアップストリームサーバーに渡されます。

たとえば、 + / match / here / please +`のリクエストがこのブロックで処理される場合、リクエストURIは `+ http://example.com/match/として + example.com + `サーバーに送信されます。 here / please + `。

代替シナリオを見てみましょう。

# server context

location /match/here {
   proxy_pass http://example.com/new/prefix;
}

. . .

上記の例では、プロキシサーバーはURIセグメントの最後に定義されています( + / new / prefix +)。 URIが `+ proxy_pass +`定義で指定されている場合、_location_定義に一致するリクエストの部分は、パス中にこのURIに置き換えられます。

たとえば、Nginxサーバーでの「+ / match / here / please 」のリクエストは、「 http://example.com/new/prefix/please+」としてアップストリームサーバーに渡されます。 `+ / match / here `は ` / new / prefix +`に置き換えられます。 これは覚えておくべき重要なポイントです。

時々、この種の交換は不可能です。 これらの場合、 `+ proxy_pass +`定義の最後のURIは無視され、クライアントからの元のURIまたは他のディレクティブによって変更されたURIが上流サーバーに渡されます。

たとえば、正規表現を使用して場所が一致する場合、NginxはURIのどの部分が式に一致したかを判断できないため、元のクライアント要求URIを送信します。 別の例は、同じ場所で書き換えディレクティブが使用され、クライアントURIが書き換えられるが、同じブロックで処理される場合です。 この場合、書き換えられたURIが渡されます。

Nginxがヘッダーを処理する方法を理解する

すぐには明らかにならないかもしれないことの1つは、アップストリームサーバーが要求を適切に処理することを期待している場合、URI以外のものを渡すことが重要であることです。 クライアントに代わってNginxから送信されるリクエストは、クライアントから直接送信されるリクエストとは異なります。 これの大部分は、リクエストに付随するヘッダーです。

Nginxがリクエストをプロキシするとき、クライアントから受信するリクエストヘッダーを自動的に調整します。

  • Nginxは空のヘッダーを取り除きます。 空の値を別のサーバーに渡す意味はありません。リクエストを膨らませるためだけに役立ちます。

  • Nginxは、デフォルトで、アンダースコアを含むヘッダーを無効と見なします。 プロキシされたリクエストからこれらを削除します。 これらを有効なものとしてNginxに解釈させたい場合、 `+ underscores_in_headers +`ディレクティブを「on」に設定できます。そうしないと、ヘッダーがバックエンドサーバーに到達しません。

  • 「Host」ヘッダーは、 `+ $ proxy_host `変数で定義された値に書き換えられます。 これは、アップストリームのIPアドレスまたは名前とポート番号になり、 ` proxy_pass +`ディレクティブで直接定義されます。

  • 「接続」ヘッダーが「閉じる」に変更されます。 このヘッダーは、2つのパーティ間で確立された特定の接続に関する情報を通知するために使用されます。 この例では、Nginxはこれを「close」に設定して、元の要求に応答するとこの接続が閉じられることを上流サーバーに示します。 アップストリームは、この接続が永続的であることを期待すべきではありません。

上記から推測できる最初のポイントは、渡したくない_ヘッダーは空の文字列に設定する必要があるということです。 空の値を持つヘッダーは、渡されたリクエストから完全に削除されます。

上記の情報から収集する次のポイントは、バックエンドアプリケーションが非標準ヘッダーを処理する場合、アンダースコアが「ない」ことを確認する必要があるということです。 アンダースコアを使用するヘッダーが必要な場合は、設定の「+ underscores_in_headers +」ディレクティブをさらに「on」に設定できます(httpコンテキストまたはIPアドレス/ポートの組み合わせのデフォルトサーバー宣言のコンテキストで有効) )。 これを行わないと、Nginxはこれらのヘッダーに無効のフラグを付け、アップストリームに渡す前に静かにドロップします。

「Host」ヘッダーは、ほとんどのプロキシシナリオで特に重要です。 上記のように、デフォルトでは、これは `+ $ proxy_host `の値に設定されます。これは、 ` proxy_pass +`定義から直接取得したドメイン名またはIPアドレスとポートを含む変数です。 これは、Nginxがアップストリームサーバーが確実に応答できる唯一のアドレスであるため、デフォルトで選択されています(接続情報から直接取得されるため)。

「Host」ヘッダーの最も一般的な値は次のとおりです。

  • + $ proxy_host +:「+ proxy_pass +」定義から取得したドメイン名またはIPアドレスとポートコンボに「Host」ヘッダーを設定します。 これはデフォルトであり、Nginxの観点からは「安全」ですが、通常、プロキシされたサーバーが要求を正しく処理するために必要なものではありません。

  • + $ http_host +:「Host」ヘッダーをクライアント要求からの「Host」ヘッダーに設定します。 クライアントから送信されたヘッダーは、変数としてNginxで常に利用可能です。 変数は接頭辞 `+ $ http_ `で始まり、その後に小文字のヘッダー名が続き、ダッシュはアンダースコアに置き換えられます。 ` $ http_host +`変数はほとんどの場合機能しますが、クライアントリクエストに有効な「Host」ヘッダーがない場合、パスが失敗する可能性があります。

  • + $ host +:この変数は、優先順位に従って設定されます:リクエスト行自体からのホスト名、クライアントリクエストからの「ホスト」ヘッダー、またはリクエストに一致するサーバー名。

ほとんどの場合、「Host」ヘッダーを「+ $ host +」変数に設定します。 これは最も柔軟性があり、通常、プロキシされたサーバーに可能な限り正確に入力された「ホスト」ヘッダーを提供します。

ヘッダーの設定またはリセット

プロキシ接続のヘッダーを調整または設定するには、 `+ proxy_set_header +`ディレクティブを使用できます。 たとえば、前述のように「Host」ヘッダーを変更し、プロキシされたリクエストに共通するヘッダーを追加するには、次のようなものを使用できます。

# server context

location /match/here {
   proxy_set_header HOST $host;
   proxy_set_header X-Forwarded-Proto $scheme;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

   proxy_pass http://example.com/new/prefix;
}

. . .

上記のリクエストは、「Host」ヘッダーを変数「+ $ host 」に設定します。この変数には、リクエストされている元のホストに関する情報が含まれている必要があります。 ` X-Forwarded-Proto +`ヘッダーは、プロキシされたサーバーに元のクライアントリクエストのスキーマに関する情報を提供します(httpまたはhttpsリクエストであったかどうか)。

`+ X-Real-IP `はクライアントのIPアドレスに設定されるため、プロキシはこの情報に基づいて正しく判断したりログを記録したりできます。 ` X-Forwarded-For`ヘッダーは、クライアントがこの時点までプロキシされたすべてのサーバーのIPアドレスを含むリストです。 上記の例では、これを `+ $ proxy_add_x_forwarded_for `変数に設定します。 この変数は、クライアントから取得した元の ` X-Forwarded-For`ヘッダーの値を取り、NginxサーバーのIPアドレスを最後に追加します。

もちろん、 `+ proxy_set_header +`ディレクティブをサーバーまたはhttpコンテキストに移動して、複数の場所で参照できるようにすることもできます。

# server context

proxy_set_header HOST $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

location /match/here {
   proxy_pass http://example.com/new/prefix;
}

location /different/match {
   proxy_pass http://example.com;
}

プロキシ接続の負荷分散のためのアップストリームコンテキストの定義

前の例では、単一のバックエンドサーバーに対して単純なHTTPプロキシを実行する方法を示しました。 Nginxでは、リクエストを渡すことができるバックエンドサーバーのプール全体を指定することで、この構成を簡単にスケールアウトできます。

これを行うには、 `+ upstream `ディレクティブを使用してサーバーのプールを定義します。 この構成では、リストされているサーバーのいずれかがクライアントの要求を処理できることを前提としています。 これにより、ほとんど労力をかけずにインフラストラクチャを拡張できます。 ` upstream +`ディレクティブは、Nginx設定のhttpコンテキストで設定する必要があります。

簡単な例を見てみましょう:

# http context

upstream  {
   server host1.example.com;
   server host2.example.com;
   server host3.example.com;
}

server {
   listen 80;
   server_name example.com;

   location /proxy-me {
       proxy_pass http://;
   }
}

上記の例では、「+ backend_hosts 」と呼ばれるアップストリームコンテキストを設定しました。 定義すると、この名前は通常のドメイン名であるかのようにプロキシパス内で使用できるようになります。 ご覧のとおり、サーバーブロック内で、 ` example.com / proxy-me /…​+`に対して行われたリクエストを上記で定義したプールに渡します。 そのプール内で、構成可能なアルゴリズムを適用してホストが選択されます。 デフォルトでは、これは単なる単純なラウンドロビン選択プロセスです(各リクエストは順番に異なるホストにルーティングされます)。

アップストリームバランシングアルゴリズムの変更

アップストリームコンテキスト内にディレクティブまたはフラグを含めることにより、アップストリームプールで使用されるバランシングアルゴリズムを変更できます。

  • (ラウンドロビン):他のバランシングディレクティブが存在しない場合に使用されるデフォルトのロードバランシングアルゴリズム。 アップストリームコンテキストで定義された各サーバーには、リクエストが順番に渡されます。

  • * + least_conn + *:アクティブな接続の数が最も少ないバックエンドに常に新しい接続を与えることを指定します。 これは、バックエンドへの接続がしばらく続く場合に特に便利です。

  • * + ip_hash + *:このバランシングアルゴリズムは、クライアントのIPアドレスに基づいて異なるサーバーにリクエストを分散します。 最初の3オクテットは、要求を処理するサーバーを決定するためのキーとして使用されます。 その結果、クライアントは毎回同じサーバーからサービスを受ける傾向があり、セッションの一貫性を保つことができます。

  • * + hash + *:このバランスアルゴリズムは、主にmemcachedプロキシで使用されます。 サーバーは、任意に提供されたハッシュキーの値に基づいて分割されます。 これは、テキスト、変数、または組み合わせにすることができます。 これは、ユーザーがデータを提供する必要がある唯一のバランス調整方法であり、ハッシュに使用する必要があるキーです。

バランシングアルゴリズムを変更すると、ブロックは次のようになります。

# http context

upstream  {

   least_conn;

   server host1.example.com;
   server host2.example.com;
   server host3.example.com;
}

. . .

上記の例では、接続が最も少ないサーバーに基づいてサーバーが選択されます。 `+ ip_hash +`ディレクティブを同じ方法で設定して、一定量のセッション「スティッキネス」を取得できます。

`+ hash +`メソッドに関しては、ハッシュするキーを提供する必要があります。 これは何でも構いません。

# http context

upstream  {

   hash $remote_addr$remote_port consistent;

   server host1.example.com;
   server host2.example.com;
   server host3.example.com;
}

. . .

上記の例では、クライアントのIPアドレスとポートの値に基づいてリクエストを分散します。 オプションのパラメーター「+ consistent +」も追加しました。これは、ketamaの一貫したハッシュアルゴリズムを実装しています。 基本的に、これは、アップストリームサーバーが変更されても、キャッシュへの影響が最小限であることを意味します。

バランシングのためのサーバーの重みの設定

バックエンドサーバーの宣言では、デフォルトで、各サーバーは等しく「重み付け」されます。 これは、各サーバーが同じ量の負荷を処理できることを想定しています(負荷分散アルゴリズムの影響を考慮して)。 ただし、宣言中にサーバーに代替の重みを設定することもできます。

# http context

upstream  {
   server host1.example.com weight=3;
   server host2.example.com;
   server host3.example.com;
}

. . .

上記の例では、 `+ host1.example.com +`は他の2つのサーバーの3倍のトラフィックを受け取ります。 デフォルトでは、各サーバーに1の重みが割り当てられます。

バッファを使用してバックエンドサーバーを解放する

多くのユーザーに関係するプロキシの問題の1つは、プロセスにサーバーを追加した場合のパフォーマンスへの影響です。 ほとんどの場合、これはNginxのバッファリングおよびキャッシング機能を利用することで大幅に軽減できます。

別のサーバーにプロキシする場合、2つの異なる接続の速度がクライアントのエクスペリエンスに影響します。

  • クライアントからNginxプロキシへの接続。

  • Nginxプロキシからバックエンドサーバーへの接続。

Nginxには、最適化するこれらの接続のいずれかに基づいて動作を調整する機能があります。

バッファなしでは、プロキシされたサーバーからデータが送信され、すぐにクライアントへの送信が開始されます。 クライアントが高速であると想定される場合、できるだけ早くクライアントにデータを取得するために、バッファリングをオフにすることができます。 バッファーを使用すると、Nginxプロキシはバックエンドの応答を一時的に保存し、このデータをクライアントにフィードします。 クライアントが遅い場合、これによりNginxサーバーはより早くバックエンドへの接続を閉じることができます。 その後、可能なペースでクライアントにデータを配信できます。

クライアントは接続速度が大きく異なる傾向があるため、Nginxはデフォルトでバッファリング設計になっています。 次のディレクティブを使用して、バッファリング動作を調整できます。 これらは、http、サーバー、または場所のコンテキストで設定できます。 サイジングディレクティブは_request_ごとに設定されるため、必要以上に大きくすると、多くのクライアントリクエストがある場合にパフォーマンスに影響を与えることに注意することが重要です。

  • * + proxy_buffering + *:このディレクティブは、このコンテキストと子コンテキストのバッファリングを有効にするかどうかを制御します。 デフォルトでは、これは「オン」です。

  • * + proxy_buffers + *:このディレクティブは、プロキシされる応答のバッファーの数(最初の引数)とサイズ(2番目の引数)を制御します。 デフォルトでは、1メモリページ( `+ 4k `または ` 8k +`のいずれか)に等しいサイズの8つのバッファーを構成します。 バッファーの数を増やすと、より多くの情報をバッファーできます。

  • * + proxy_buffer_size + *:ヘッダーを含むバックエンドサーバーからの応答の最初の部分は、残りの応答とは別にバッファリングされます。 このディレクティブは、応答のこの部分のバッファーのサイズを設定します。 デフォルトでは、これは `+ proxy_buffers +`と同じサイズになりますが、これはヘッダー情報に使用されるため、通常はより小さな値に設定できます。

  • * + proxy_busy_buffers_size + *:このディレクティブは、「client-ready」とマークされてビジーになることができるバッファーの最大サイズを設定します。 クライアントは一度に1つのバッファからしかデータを読み取ることができませんが、バッファはキューに配置されて、クライアントにまとめて送信されます。 このディレクティブは、この状態にできるバッファスペースのサイズを制御します。

  • * + proxy_max_temp_file_size + *:これは、ディスク上の一時ファイルのリクエストごとの最大サイズです。 これらは、アップストリームの応答が大きすぎてバッファに収まらない場合に作成されます。

  • * + proxy_temp_file_write_size + *:これは、プロキシされたサーバーの応答が設定されたバッファーに対して大きすぎる場合に、Nginxが一時ファイルに一度に書き込むデータの量です。

  • * + proxy_temp_path + *:これは、上流サーバーからの応答が設定されたバッファーに収まらない場合にNginxが一時ファイルを保存するディスク上の領域へのパスです。

ご覧のとおり、Nginxはバッファリング動作を微調整するための非常に多くの異なるディレクティブを提供しています。 ほとんどの場合、これらの大部分について心配する必要はありませんが、これらの値の一部を調整すると便利です。 調整するのに最も便利なのは、 `+ proxy_buffers `および ` proxy_buffer_size +`ディレクティブです。

各アップストリームリクエストで使用可能なプロキシバッファーの数を増やし、ヘッダーを格納する可能性のあるバッファーを削減する例は次のようになります。

# server context

proxy_buffering on;
proxy_buffer_size 1k;
proxy_buffers 24 4k;
proxy_busy_buffers_size 8k;
proxy_max_temp_file_size 2048m;
proxy_temp_file_write_size 32k;

location / {
   proxy_pass http://example.com;
}

対照的に、すぐにデータを提供したい高速クライアントがある場合は、バッファリングを完全にオフにすることができます。 アップストリームがクライアントより速い場合、Nginxは実際にバッファを実際に使用しますが、バッファがプールされるのを待つのではなく、すぐにクライアントにデータをフラッシュしようとします。 クライアントが遅い場合、クライアントが追いつくまでアップストリーム接続が開いたままになる可能性があります。 バッファリングが「オフ」の場合、 `+ proxy_buffer_size +`ディレクティブで定義されたバッファのみが使用されます:

# server context

proxy_buffering off;
proxy_buffer_size 4k;

location / {
   proxy_pass http://example.com;
}

高可用性(オプション)

Nginxプロキシは、ロードバランサーの冗長セットを追加して高可用性インフラストラクチャを作成することにより、より堅牢にできます。

高可用性(HA)セットアップは、単一障害点のないインフラストラクチャであり、ロードバランサーはこの構成の一部です。 複数のロードバランサーを使用することにより、ロードバランサーが利用できない場合や、メンテナンスのためにロードバランサーを停止する必要がある場合に、潜在的なダウンタイムを防ぎます。

基本的な高可用性セットアップの図を次に示します。

画像:https://assets.digitalocean.com/articles/high_availability/ha-diagram-animated.gif [HAセットアップ]

この例では、1つのサーバーから別のサーバーに再マップできる静的IPアドレスの背後に、複数のロードバランサー(1つはアクティブで、1つ以上はパッシブ)があります。 クライアント要求は、静的IPからアクティブなロードバランサーにルーティングされ、その後バックエンドサーバーにルーティングされます。 詳細については、https://www.digitalocean.com/community/tutorials/how-to-use-floating-ips-on-digitalocean#how-to-implement-an-ha-setup [How ToのこのセクションフローティングIPを使用する]。

応答時間を短縮するためのプロキシキャッシングの構成

バッファリングはより多くのリクエストを処理するためにバックエンドサーバーを解放するのに役立ちますが、Nginxはバックエンドサーバーからコンテンツをキャッシュする方法も提供し、多くのリクエストに対してアップストリームに接続する必要性を排除します。

プロキシキャッシュの構成

プロキシされたコンテンツに使用するキャッシュを設定するには、 `+ proxy_cache_path `ディレクティブを使用できます。 これにより、プロキシされたサーバーから返されたデータを保持できる領域が作成されます。 ` proxy_cache_path +`ディレクティブはhttpコンテキストで設定する必要があります。

以下の例では、これといくつかの関連するディレクティブを構成して、キャッシュシステムをセットアップします。

# http context

proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=backcache:8m max_size=50m;
proxy_cache_key "$scheme$request_method$host$request_uri$is_args$args";
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;

`+ proxy_cache_path `ディレクティブで、キャッシュを保存したいファイルシステム上のディレクトリを定義しました。 この例では、 ` / var / lib / nginx / cache +`ディレクトリを選択しました。 このディレクトリが存在しない場合は、次のように入力して、正しい許可と所有権で作成できます。

sudo mkdir -p /var/lib/nginx/cache
sudo chown www-data /var/lib/nginx/cache
sudo chmod 700 /var/lib/nginx/cache

`+ levels = +`パラメーターは、キャッシュの編成方法を指定します。 Nginxは、キーの値をハッシュすることによりキャッシュキーを作成します(以下で設定)。 上記で選択したレベルは、2文字のサブディレクトリ(ハッシュ値の末尾から次の2文字から取得)を持つ1文字のディレクトリ(これがハッシュ値の最後の文字になります)が作成されることを示しています。 通常、これの詳細を気にする必要はありませんが、Nginxが関連する値をすばやく見つけるのに役立ちます。

`+ keys_zone = `パラメータは、このキャッシュゾーンの名前を定義します。これは、 ` backcache `と呼ばれています。 これは、保存するメタデータの量を定義する場所でもあります。 この場合、8 MBのキーを保存しています。 Nginxは、メガバイトごとに約8000エントリを保存できます。 ` max_size +`パラメータは、実際にキャッシュされるデータの最大サイズを設定します。

上記で使用する別のディレクティブは `+ proxy_cache_key +`です。 これは、キャッシュされた値を保存するために使用されるキーを設定するために使用されます。 この同じキーを使用して、キャッシュからリクエストを処理できるかどうかを確認します。 これをスキーム(httpまたはhttps)、HTTP要求メソッド、および要求されたホストとURIの組み合わせに設定しています。

`+ proxy_cache_valid +`ディレクティブは複数回指定できます。 これにより、ステータスコードに応じて値を保存する期間を設定できます。 この例では、成功とリダイレクトを10分間保存し、毎分404応答のキャッシュを期限切れにします。

キャッシュゾーンを構成しましたが、キャッシュを使用するタイミングをNginxに伝える必要があります。

バックエンドにプロキシする場所で、このキャッシュの使用を構成できます。

# server context

location /proxy-me {
   proxy_cache backcache;
   proxy_cache_bypass $http_cache_control;
   add_header X-Proxy-Cache $upstream_cache_status;

   proxy_pass http://backend;
}

. . .

`+ proxy_cache `ディレクティブを使用して、このコンテキストに ` backcache +`キャッシュゾーンを使用するように指定できます。 Nginxは、バックエンドに渡す前に有効なエントリをここで確認します。

`+ proxy_cache_bypass `ディレクティブは ` $ http_cache_control +`変数に設定されます。 これには、クライアントが新しい非キャッシュバージョンのリソースを明示的に要求しているかどうかに関するインジケータが含まれます。 このディレクティブを設定すると、Nginxはこれらのタイプのクライアントリクエストを正しく処理できます。 これ以上の構成は必要ありません。

また、「+ X-Proxy-Cache」という追加のヘッダーを追加しました。 このヘッダーを `+ $ upstream_cache_status +`変数の値に設定します。 基本的に、これにより、リクエストによってキャッシュヒット、キャッシュミス、またはキャッシュが明示的にバイパスされたかどうかを確認できるヘッダーが設定されます。 これは特にデバッグに役立ちますが、クライアントにとっても有益な情報です。

キャッシュ結果に関する注意

キャッシュを使用すると、プロキシのパフォーマンスを大幅に改善できます。 ただし、キャッシュを構成する際には、留意すべき考慮事項が必ずあります。

まず、ユーザー関連のデータをキャッシュしないでください。 これにより、あるユーザーのデータが別のユーザーに表示される可能性があります。 サイトが完全に静的である場合、これはおそらく問題ではありません。

サイトに動的な要素がある場合は、バックエンドサーバーでこれを考慮する必要があります。 これをどのように処理するかは、バックエンド処理を処理しているアプリケーションまたはサーバーによって異なります。 プライベートコンテンツの場合、データの性質に応じて、 `+ Cache-Control`ヘッダーを" no-cache "、" no-store "、または" private "に設定する必要があります。

  • * no-cache *:バックエンドでデータが変更されていないことを最初に確認せずに、応答を再度提供しないことを示します。 これは、データが動的で重要な場合に使用できます。 ETagハッシュメタデータヘッダーは各リクエストでチェックされ、バックエンドが同じハッシュ値を返す場合、以前の値を提供できます。

  • * no-store *:受信したデータをキャッシュするべきではないことを示します。 これは、データを毎回サーバーから取得する必要があることを意味するため、プライベートデータの最も安全なオプションです。

  • * private *:これは、このデータをキャッシュする共有キャッシュスペースがないことを示します。 これは、ユーザーのブラウザがデータをキャッシュできることを示すのに役立ちますが、プロキシサーバーはこのデータを後続のリクエストで有効と見なすべきではありません。

  • * public *:これは、応答が接続の任意の時点でキャッシュできるパブリックデータであることを示します。

この動作を制御できる関連ヘッダーは、「+ max-age +」ヘッダーです。これは、リソースをキャッシュする秒数を示します。

コンテンツの機密性に応じてこれらのヘッダーを正しく設定すると、プライベートデータの安全性と動的データの新鮮さを保ちながら、キャッシュを活用できます。

バックエンドもNginxを使用している場合、 `+ expires `ディレクティブを使用してこれの一部を設定できます。これにより、 ` Cache-Control `に対して ` max-age +`が設定されます。

location / {
   expires 60m;
}

location /check-me {
   expires -1;
}

上記の例では、最初のブロックにより、コンテンツを1時間キャッシュできます。 2番目のブロックは、「+ Cache-Control」ヘッダーを「no-cache」に設定します。 他の値を設定するには、次のように `+ add_header +`ディレクティブを使用できます。

location /private {
   expires -1;
   add_header Cache-Control "no-store";
}

結論

Nginxは何よりもまずリバースプロキシであり、たまたまWebサーバーとして機能することもあります。 この設計上の決定により、他のサーバーへのリクエストのプロキシはかなり簡単です。 Nginxは非常に柔軟性があり、必要に応じてプロキシ設定をより複雑に制御できます。

前の投稿:JenkinsのリバースプロキシとしてSSLを使用してNginxを構成する方法
次の投稿:Debian 9でNginxの自己署名SSL証明書を作成する方法