NginxHTTPプロキシ、負荷分散、バッファリング、およびキャッシングについて理解する

提供:Dev Guides
移動先:案内検索

序章

このガイドでは、Nginxのhttpプロキシ機能について説明します。これにより、Nginxはリクエストをバックエンドhttpサーバーに渡してさらに処理することができます。 Nginxは、インフラストラクチャをスケールアウトしたり、大きなクライアント負荷を処理するように設計されていない他のサーバーにリクエストを渡したりするためのリバースプロキシソリューションとして設定されることがよくあります。

その過程で、Nginxの組み込みの負荷分散機能を使用してスケールアウトする方法について説明します。 また、クライアントのプロキシ操作のパフォーマンスを向上させるためのバッファリングとキャッシングについても説明します。

一般的なプロキシ情報

過去に単純な単一サーバー構成でWebサーバーのみを使用したことがある場合は、なぜ要求をプロキシする必要があるのか疑問に思われるかもしれません。

Nginxから他のサーバーにプロキシする理由の1つは、インフラストラクチャをスケールアウトする機能です。 Nginxは、同時に多くの同時接続を処理するように構築されています。 これにより、クライアントの連絡窓口として理想的です。 サーバーは、任意の数のバックエンドサーバーにリクエストを渡して、作業の大部分を処理できます。これにより、インフラストラクチャ全体に負荷が分散されます。 この設計により、バックエンドサーバーを簡単に追加したり、メンテナンスのために必要に応じてサーバーを停止したりする際の柔軟性も得られます。

httpプロキシが役立つ可能性のある別の例は、実稼働環境のクライアントからの要求を直接処理するように構築されていない可能性のあるアプリケーションサーバーを使用する場合です。 多くのフレームワークには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/here/pleaseとしてexample.comサーバーに送信されます。

別のシナリオを見てみましょう。

# server context

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

. . .

上記の例では、プロキシサーバーは最後にURIセグメント(/new/prefix)で定義されています。 proxy_pass定義でURIが指定されている場合、 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ディレクティブを「オン」に設定できます。そうしないと、ヘッダーがバックエンドサーバーに到達しません。
  • 「Host」ヘッダーは、$proxy_host変数で定義された値に書き換えられます。 これは、proxy_passディレクティブで直接定義されている、アップストリームのIPアドレスまたは名前とポート番号になります。
  • 「接続」ヘッダーが「閉じる」に変更されます。 このヘッダーは、2つのパーティ間で確立された特定の接続に関する情報を通知するために使用されます。 この場合、Nginxはこれを「閉じる」に設定して、元のリクエストが応答されるとこの接続が閉じられることをアップストリームサーバーに示します。 アップストリームは、この接続が永続的であることを期待するべきではありません。

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

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

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

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

  • $proxy_host:これは、「Host」ヘッダーを、proxy_pass定義から取得したドメイン名またはIPアドレスとポートの組み合わせに設定します。 これはNginxの観点からはデフォルトで「安全」ですが、通常、プロキシサーバーがリクエストを正しく処理するために必要なものではありません。
  • $http_host:クライアントリクエストの「Host」ヘッダーを「Host」ヘッダーに設定します。 クライアントから送信されたヘッダーは、Nginxでは常に変数として使用できます。 変数は$http_プレフィックスで始まり、その後に小文字のヘッダー名が続き、ダッシュはアンダースコアに置き換えられます。 $http_host変数はほとんどの場合機能しますが、クライアント要求に有効な「ホスト」ヘッダーがない場合、パスが失敗する可能性があります。
  • $host:この変数は、優先順に、要求行自体のホスト名、クライアント要求の「Host」ヘッダー、または要求に一致するサーバー名に設定されます。

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

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

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

# 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 backend_hosts {
    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;
    }
}

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

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

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

  • (ラウンドロビン):他のバランシングディレクティブが存在しない場合に使用されるデフォルトのロードバランシングアルゴリズム。 アップストリームコンテキストで定義された各サーバーには、要求が順番に渡されます。
  • least_conn :アクティブな接続の数が最も少ないバックエンドに常に新しい接続を与える必要があることを指定します。 これは、バックエンドへの接続がしばらく続く可能性がある状況で特に役立ちます。
  • ip_hash :このバランシングアルゴリズムは、クライアントのIPアドレスに基づいて異なるサーバーにリクエストを分散します。 最初の3つのオクテットは、要求を処理するサーバーを決定するためのキーとして使用されます。 その結果、クライアントは毎回同じサーバーからサービスを受ける傾向があり、セッションの一貫性を保つのに役立ちます。
  • hash :このバランシングアルゴリズムは、主にmemcachedプロキシで使用されます。 サーバーは、任意に提供されたハッシュキーの値に基づいて分割されます。 これは、テキスト、変数、または組み合わせにすることができます。 これは、ハッシュに使用する必要のあるキーであるデータをユーザーが提供する必要がある唯一のバランシング方法です。

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

# http context

upstream backend_hosts {

    least_conn;

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

. . .

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

hashメソッドについては、ハッシュの対象となるキーを指定する必要があります。 これはあなたが望むものなら何でもかまいません:

# http context

upstream backend_hosts {

    hash $remote_addr$remote_port consistent;

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

. . .

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

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

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

# http context

upstream backend_hosts {
    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、サーバー、またはロケーションのコンテキストで設定できます。 サイズ設定ディレクティブはリクエストごとに構成されているため、必要以上に増やすと、クライアントリクエストが多い場合にパフォーマンスに影響を与える可能性があることに注意してください。

  • proxy_buffering :このディレクティブは、このコンテキストと子コンテキストのバッファリングを有効にするかどうかを制御します。 デフォルトでは、これは「オン」です。
  • proxy_buffers :このディレクティブは、プロキシされた応答のバッファーの数(最初の引数)とサイズ(2番目の引数)を制御します。 デフォルトでは、1メモリページに等しいサイズの8つのバッファ(4kまたは8k)を構成します。 バッファの数を増やすと、より多くの情報をバッファリングできるようになります。
  • proxy_buffer_size :ヘッダーを含むバックエンドサーバーからの応答の最初の部分は、残りの応答とは別にバッファリングされます。 このディレクティブは、応答のこの部分のバッファーのサイズを設定します。 デフォルトでは、これはproxy_buffersと同じサイズになりますが、これはヘッダー情報に使用されるため、通常はこれより低い値に設定できます。
  • proxy_busy_buffers_size :このディレクティブは、「クライアント対応」とマークしてビジーにすることができるバッファーの最大サイズを設定します。 クライアントは一度に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)セットアップは、単一障害点のないインフラストラクチャであり、ロードバランサーはこの構成の一部です。 複数のロードバランサーを使用することで、ロードバランサーが使用できない場合、またはメンテナンスのためにロードバランサーを停止する必要がある場合に、潜在的なダウンタイムを防ぐことができます。

これは、基本的な高可用性セットアップの図です。

この例では、あるサーバーから別のサーバーに再マッピングできる静的IPアドレスの背後に複数のロードバランサー(1つはアクティブで1つ以上のパッシブ)があります。 クライアントリクエストは、静的IPからアクティブなロードバランサーにルーティングされ、次にバックエンドサーバーにルーティングされます。 詳細については、フローティング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と呼びます。 これは、保存するメタデータの量を定義する場所でもあります。 この場合、8MBのキーを保存しています。 メガバイトごとに、Nginxは約8000エントリを保存できます。 max_sizeパラメーターは、実際にキャッシュされるデータの最大サイズを設定します。

上記で使用するもう1つのディレクティブは、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-Controlmax-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は非常に柔軟性があり、必要に応じてプロキシ構成をより複雑に制御できます。