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

前書き

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

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

一般的なプロキシ情報

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

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

HTTPプロキシが役立つもう1つの例は、実稼働環境のクライアントからの要求を直接処理するように構築されていないアプリケーションサーバーを使用する場合です。 多くのフレームワークにはWebサーバーが含まれていますが、それらのほとんどはNginxのような高パフォーマンス用に設計されたサーバーほど堅牢ではありません。 Nginxをこれらのサーバーの前に配置すると、ユーザーのエクスペリエンスが向上し、セキュリティが向上します。

Nginxでのプロキシは、Nginxサーバーを対象としたリクエストを操作し、実際の処理のために他のサーバーに渡すことで実現されます。 リクエストの結果はNginxに返され、Nginxは情報をクライアントに中継します。 このインスタンスの他のサーバーは、リモートマシン、ローカルサーバー、またはNginx内で定義された他の仮想サーバーです。 Nginxプロキシがリクエストするサーバーは、upstream serversと呼ばれます。

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を送信します。 別の例は、同じ場所内でrewriteディレクティブが使用され、クライアントURIが書き換えられるが、それでも同じブロックで処理される場合です。 この場合、書き換えられたURIが渡されます。

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

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

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

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

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

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

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

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

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

「Host」ヘッダーは、ほとんどのプロキシシナリオで特に重要です。 上記のように、デフォルトでは、これは$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ディレクティブを使用できます。 たとえば、前述のように「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 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/...に対して行われたすべてのリクエストを上記で定義したプールに渡します。 そのプール内で、構成可能なアルゴリズムを適用してホストが選択されます。 デフォルトでは、これは単なる単純なラウンドロビン選択プロセスです(各リクエストは順番に異なるホストにルーティングされます)。

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

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

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

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

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

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

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

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

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

HA Setup

この例では、1つのサーバーから別のサーバーに再マップできる静的IPアドレスの背後に、複数のロードバランサー(1つはアクティブで、1つ以上はパッシブ)があります。 クライアント要求は、静的IPからアクティブなロードバランサーにルーティングされ、その後バックエンドサーバーにルーティングされます。 詳細については、this section of How To Use Floating IPsを参照してください。

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

バッファリングはより多くのリクエストを処理するためにバックエンドサーバーを解放するのに役立ちますが、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変数の値に設定します。 基本的に、これにより、リクエストによってキャッシュヒット、キャッシュミス、またはキャッシュが明示的にバイパスされたかどうかを確認できるヘッダーが設定されます。 これは特にデバッグに役立ちますが、クライアントにとっても有益な情報です。

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

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

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

サイトに動的な要素がある場合は、バックエンドサーバーでこれを考慮する必要があります。 これをどのように処理するかは、バックエンド処理を処理しているアプリケーションまたはサーバーによって異なります。 プライベートコンテンツの場合、データの性質に応じて、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は非常に柔軟性があり、必要に応じてプロキシ設定をより複雑に制御できます。