オペレーターが知っておくべき 18 個の Nginx プロキシ キャッシュ構成のヒント (どれを知っていますか?)

オペレーターが知っておくべき 18 個の Nginx プロキシ キャッシュ構成のヒント (どれを知っていますか?)

アプリケーションや Web サイトのパフォーマンスが成功の重要な要素であることは誰もが知っています。ただし、アプリや Web サイトのパフォーマンスを向上させるプロセスは必ずしも明確ではありません。コードの品質とインフラストラクチャはもちろん重要ですが、多くの場合、いくつかの非常に基本的なアプリケーション配信テクニックに重点を置くことで、アプリケーションのエンドユーザー エクスペリエンスを大幅に改善できます。

一例として、アプリケーション スタックでのキャッシュの実装と最適化が挙げられます。このチュートリアルで紹介するテクニックは、初心者と上級ユーザーの両方が Nginx に含まれるコンテンツ キャッシュ機能を使用してパフォーマンスを向上させるのに役立ちます。

概要

コンテンツ キャッシュは、クライアントとオリジン サーバー (アップストリーム) の間に配置され、表示されるすべてのコンテンツのコピーを保持します。クライアントがキャッシュにすでに保存されているコンテンツを要求した場合、オリジン サーバーに接続せずにコンテンツを直接返します。これにより、コンテンツがクライアントの近くにキャッシュされるためパフォーマンスが向上し、毎回ページを最初から生成する必要がなくなるため、アプリケーション サーバーをより効率的に使用できるようになります。

Web ブラウザとアプリケーション サーバーの間には、クライアントのブラウザ キャッシュ、中間キャッシュ、コンテンツ配信ネットワーク (CDN)、アプリケーション サーバーの前にあるロード バランサまたはリバース プロキシなど、複数のキャッシュが存在する場合があります。リバース プロキシ/ロード バランサー レベルでも、キャッシュによってパフォーマンスが大幅に向上します。

例を挙げます。私のサイトでは、Next.js のサーバーポートレンダリングを使用しています。サーバーのパフォーマンスは比較的悪いので、もちろん 5 ドルのサーバーなので、それほど良いとは期待できません。使用できるということ自体がすでに非常に優れています。この LAN にアクセスできる程度には十分です。あまり期待しないでください。

毎回ページを開くのに、ネットワーク遅延も含め約 7 秒かかります。しかし、サーバー (127.0.0.1) に直接リクエストすると、5 秒近くかかります。すると、データベースからデータを取得する時間を除くと、サーバー側のレンダリング時間は 4.5 秒かかり、遅すぎます。現時点で考えられる最速の解決策はキャッシュですが、そこにキャッシュを追加すると、各ステップの時間から判断すると、Nginx にキャッシュを追加するのが問題解決の最も早い方法です。

Nginx は、アプリケーション スタック内のリバース プロキシまたはロード バランサとして導入されることが多く、完全なキャッシュ機能を備えています。以下では、Nginx で基本的なキャッシュを構成する方法について説明します。

基本的なキャッシュの設定方法

基本的なキャッシュを有効にするには、proxy_cache_path と proxy_cache の 2 つのディレクティブだけが必要です。

proxy_cache_path ディレクティブはキャッシュのパスと構成を設定し、proxy_cache ディレクティブはそれを有効にするために使用されます。

proxy_cache_path /path/to/cache レベル=1:2 キーゾーン=my_cache:10m 最大サイズ=10g 
         非アクティブ=60m use_temp_path=オフ; 
 
 
サーバー{ 
  # ... 
  位置 / { 
    proxy_cache my_cache; 
    proxy_pass http://my_upstream; 
  } 
}

proxy_cache_path ディレクティブのパラメータは、次の設定を定義します。

キャッシュされたローカル ディスク ディレクトリは /path/to/cache/ と呼ばれます。

  • levels /path/to/cache/ の下に 2 レベルのディレクトリ階層を設定します。 1 つのディレクトリに多数のファイルがあるとファイル アクセスが遅くなる可能性があるため、ほとんどの展開では 2 レベルのディレクトリ階層を推奨します。 levels にこのパラメータが含まれていない場合、Nginx はすべてのファイルを同じディレクトリに配置します。
  • keys_zone は、タイマーで使用する場合など、キャッシュ キーとメタデータを格納するために使用される共有メモリ ゾーンを設定します。 Nginx はメモリ内にキーのコピーを持っているため、ディスクにアクセスすることなくリクエストが HIT か MISS かをすぐに判断でき、チェックの速度が大幅に向上します。 1 MB の領域には約 8,000 個のキーのデータが保存できるため、例で構成された 10 MB の領域には約 80,000 個のキーのデータが保存できます。
  • max_size はキャッシュ サイズの上限を設定します (この場合は 10 ギガバイト)。これはオプションです。値を指定しないと、キャッシュが拡張され、使用可能なディスク領域がすべて使用されます。キャッシュ サイズが制限に達すると、キャッシュ マネージャーと呼ばれるプロセスが最も最近使用されていないキャッシュ ファイルを削除して、サイズを制限以下に復元します。
  • 非アクティブ アイテムがアクセスされずにキャッシュ内に残っていられる期間を指定します。この例では、キャッシュ マネージャー プロセスは、有効期限が切れているかどうかに関係なく、60 分間要求されていないファイルをキャッシュから自動的に削除します。デフォルト値は10分(10m)です。非アクティブなコンテンツは期限切れのコンテンツとは異なります。 Nginx は、期限切れのコンテンツを定義するキャッシュ ヘッダー (Cache-Control: max-age=120 など) を自動的に削除しません。期限切れ(古くなった)コンテンツは、指定された期間アクセスされていない場合にのみ削除されます。古いコンテンツにアクセスすると、Nginx は元のサーバーからそのコンテンツを更新し、非アクティブ タイマーをリセットします。
  • Nginx はまず、キャッシュ用のファイルを一時ストレージ領域に書き込みます。use_temp_path=off ディレクティブは、キャッシュされる同じディレクトリにファイルを書き込むように NGINX に指示します。ファイル システム間でのデータの不要なコピーを回避するために、このパラメータをオフに設定することをお勧めします。 use_temp_path は Nginx 1.7.10 で導入されました。

最後に、proxy_cache ディレクティブは、親ロケーション ブロックの URL (例では /) に一致するすべてのコンテンツのキャッシュを有効にします。また、サーバー ブロックに proxy_cache ディレクティブを含めることもできます。これは、独自の location ディレクティブを持たないサーバーのすべてのブロックに適用されます。

アップストリームサーバーがダウンしているときにキャッシュされたコンテンツを提供する()

Nginx コンテンツ キャッシュの強力な機能は、オリジン サーバーから新しいコンテンツを取得できない場合に、キャッシュからキャッシュされたコンテンツを提供するように Nginx を構成できることです。これは、リソースをキャッシュするすべてのオリジン サーバーがダウンしているか、一時的に占有されている場合に発生する可能性があります。

Nginx は、エラーをクライアントに渡す代わりに、キャッシュからファイルの古いバージョンを提供します。これにより、Nginx プロキシ サーバーのフォールト トレランスが強化され、サーバー障害やトラフィックの急増が発生した場合でも稼働時間が確保されます。この機能を有効にするには、proxy_cache_use_stale ディレクティブを追加します。

位置 / { 
  # ... 
  proxy_cache_use_stale エラー タイムアウト http_500 http_502 http_503 http_504; 
}

この例の構成では、Nginx がオリジン サーバーからエラー、タイムアウト、または指定された 5xx エラーのいずれかを受信し、要求されたファイルの古いバージョンがキャッシュ内にある場合、エラーをクライアントに転送するのではなく、古いファイルを配信します。

キャッシュパフォーマンスを向上させる方法

Nginx には、キャッシュのパフォーマンスを微調整するために使用できるオプション設定が豊富に用意されています。以下に、それらのいくつかをアクティブ化する例を示します。

proxy_cache_path /path/to/cache レベル=1:2 キーゾーン=my_cache:10m 最大サイズ=10g 
         非アクティブ=60m use_temp_path=オフ; 
 
 
サーバー{ 
  # ... 
  位置 / { 
    proxy_cache my_cache; 
    proxy_cache_revalidate をオン; 
    proxy_cache_min_uses 3; 
    proxy_cache_use_stale エラー タイムアウト 更新中 http_500 http_502 
               http_503 http_504; 
    proxy_cache_background_update をオン; 
    proxy_cache_lock オン; 
 
 
    proxy_pass http://my_upstream; 
  } 
}

これらのディレクティブは、次の動作を構成します。

  • proxy_cache_revalidate は、GET 条件付きリクエストを使用するときに、Nginx にオリジン サーバーからのコンテンツを更新するように指示します。クライアントが Cache-Control ヘッダーで定義されているようにキャッシュされているが期限切れのコンテンツを要求した場合、Nginx は GET 要求のヘッダーに If-Modified-Since フィールドを含め、それをオリジン サーバーに送信します。サーバーは、Nginx が最初にファイルをキャッシュしたときにファイルに追加されたヘッダー Last-Modified に記録された時刻以降にアイテム全体が変更されたかどうかのみを認識するためです。
  • proxy_cache_min_uses は、Nginx がリクエストをキャッシュする前にクライアントがリクエストを要求する回数を設定します。これは、最も頻繁にアクセスされるアイテムのみがキャッシュに追加されることを保証するため、キャッシュが常にいっぱいになっている場合に便利です。デフォルトでは、proxy_cache_min_uses は 1 に設定されています。
  • ディレクティブ更新パラメータ proxy_cache_use_stale と、有効化された proxy_cache_background_update ディレクティブを組み合わせると、クライアントがオリジン サーバーから期限切れまたは更新中のアイテムを要求したときに、Nginx に古いコンテンツを配信するように指示します。すべての更新はバックグラウンドで実行されます。更新されたファイルが完全にダウンロードされるまで、すべてのリクエストに対して古いファイルが返されます。
  • proxy_cache_lock を有効にすると、複数のクライアントがキャッシュにないファイル (MISS) を要求した場合、これらの要求のうち最初のものだけがオリジン サーバーを通過します。残りのリクエストは、このリクエストが満たされるまで待機し、その後キャッシュからファイルを取得します。 proxy_cache_lock が有効になっていない場合、キャッシュ ミスとなるすべてのリクエストはオリジン サーバーに直接送信されます。

キャッシュを複数のハードディスクに分割する

複数のハードドライブがある場合は、Nginx を使用してそれらの間でキャッシュを分割できます。次の例では、リクエスト URI に基づいて、クライアントを 2 つのハード ドライブに均等に分散します。

proxy_cache_path /path/to/hdd1 レベル=1:2 キーゾーン=my_cache_hdd1:10m 
         max_size=10g 非アクティブ=60m use_temp_path=オフ; 
proxy_cache_path /path/to/hdd2 レベル=1:2 キーゾーン=my_cache_hdd2:10m 
         max_size=10g 非アクティブ=60m use_temp_path=オフ; 
 
 
分割クライアント $request_uri $my_cache { 
       50% "my_cache_hdd1"; 
       50% "my_cache_hdd2"; 
} 
 
 
サーバー{ 
  # ... 
  位置 / { 
    proxy_cache $my_cache; 
    proxy_pass http://my_upstream; 
  } 
}

2 つの proxy_cache_path ディレクティブは、2 つの異なるハード ドライブ上の 2 つのキャッシュ (my_cache_hdd1 と my_cache_hdd2) を定義します。

split_clients 構成ブロックは、リクエストの半分 (結果的に 50%) が my_cache_hdd1 にキャッシュされ、残りの半分が my_cache_hdd2 にキャッシュされることを指定します。どのキャッシュを使用するかは、$request_uri 変数 (リクエスト URI) のハッシュに基づいてリクエストごとに決定され、その結果、特定の URI のリクエストは常に同じキャッシュにキャッシュされます。

この方法は RAID ハード ドライブ セットアップの代替ではないことに注意してください。ハード ドライブに障害が発生すると、障害が発生したハード ドライブへの要求に対して 500 応答コードがユーザーに表示されるなど、予期しないシステム動作が発生する可能性があります。適切な RAID ドライブ設定により、ドライブ障害に対処できます。

Nginx キャッシュを検出する方法

検出のためにレスポンスヘッダーに$upstream_cache_status変数を追加することができます。

add_header X-Cache-Status $upstream_cache_status;

この例では、クライアントへの応答に X-Cache-Status HTTP ヘッダーを追加します。 $upstream_cache_status に指定できる値は次のとおりです。

  • MISS - キャッシュ内に応答が見つからなかったため、元のサーバーから応答が取得されました。その後、応答はキャッシュされます。
  • BYPASS - リクエストが proxy_cache_bypass ディレクティブと一致したため、レスポンスはキャッシュから提供されるのではなく、オリジン サーバーから取得されました。
  • EXPIRED - キャッシュ内のエントリの有効期限が切れています。応答には、元のサーバーからの新しいコンテンツが含まれます。
  • STALE - オリジン サーバーが適切に応答していないが proxy_cache_use_stale が設定されているため、コンテンツは古くなっています。
  • 更新中 - エントリは以前のリクエストに応じて現在更新中であり、proxy_cache_use_stale 更新が設定されているため、コンテンツは古くなっています。
  • REVALIDATED - proxy_cache_revalidate ディレクティブが有効になっており、Nginx は (If-Modified-Since または If-None-Match) を介して現在キャッシュされているコンテンツがまだ有効であることを確認します。
  • HIT - 応答は有効なキャッシュから直接取得されました

Nginx がレスポンスをキャッシュするかどうかを決定する方法

デフォルトでは、Nginx はオリジン サーバーの Cache-Control ヘッダーを尊重します。応答ヘッダーで Cache-Control が Private、No-Cache、No-Store、または Set-Cookie に設定されている応答はキャッシュされません。 Nginx は GET および HEAD クライアント要求のみをキャッシュします。以下の回答で説明されているように、これらのデフォルトを上書きできます。

proxy_buffering がオフに設定されている場合、Nginx は応答をキャッシュしません。デフォルト。

NginxはCache-Controlを無視できますか?

proxy_ignore_headersディレクティブを使用してCache-Controlを無視する

場所 /images/ { 
  proxy_cache my_cache; 
  proxy_ignore_headers キャッシュ制御; 
  proxy_cache_valid は 30 分です。 
  # ... 
}

Nginx は、/images/ の下にあるすべてのものの Cache-Control ヘッダーを無視します。このディレクティブは、ヘッダーが無視される場合に必要となる、キャッシュされたデータの有効期限を強制します。 Nginx は期限が切れていないファイルをキャッシュしません。

NginxはSet-Cookieを無視できますか?

proxy_ignore_headers ディレクティブを使用します。

Nginx で POST リクエストをキャッシュする方法

proxy_cache_methods ディレクティブを使用します:

proxy_cache_methods GET HEAD POST;

この例では、POST リクエストのキャッシュを有効にします。

Cache-Control ヘッダーが許可する限り、Nginx が動的コンテンツをキャッシュする方法。動的コンテンツを短時間でもキャッシュすると、元のサーバーとデータベースの負荷が軽減され、リクエストごとにページを再生成する必要がなくなるため、最初のバイトまでの時間が短縮されます。

Nginx キャッシュを無効にする方法

proxy_cache_bypass ディレクティブ

位置 / { 
  proxy_cache_bypass $cookie_nocache $arg_nocache; 
  # ... 
}

このディレクティブは、Nginx が最初にキャッシュ内でコンテンツを検索するのではなく、すぐにオリジン サーバーにコンテンツを要求するリクエストの種類を定義します。これは、キャッシュに「穴を開ける」と呼ばれることもあります。

Nginx はどのキャッシュ キーを使用しますか?

Nginx によって生成されるキーのデフォルトの形式は、次の Nginx 変数の MD5 ハッシュのようになります: $scheme$proxy_host$request_uri; 実際に使用されるアルゴリズムは少し複雑です。

proxy_cache_path /path/to/cache レベル=1:2 キーゾーン=my_cache:10m 最大サイズ=10g 
         非アクティブ=60m use_temp_path=オフ; 
 
 
サーバー{ 
  # ... 
  位置 / { 
    proxy_cache my_cache; 
    proxy_pass http://my_upstream; 
  } 
}

この例の設定では、キャッシュ キー http://www.example.org/my_image.jpg は md5("http://my_upstream:80/my_image.jpg") として計算されます。

proxy_host 変数はハッシュ値に使用され、実際のホスト名 (www.example.com) には使用されないことに注意してください。 proxy_host は、proxy_pass ディレクティブで指定されたプロキシ サーバーの名前とポートとして定義されます。

キーの基準として使用される変数を変更するには、proxy_cache_key ディレクティブを使用します。

キャッシュキーの一部としてクッキーを使用する

キャッシュ キーは任意の値で構成できます。例:

proxy_cache_key $proxy_host$request_uri$cookie_jessionid;

この例では、JSESSIONID Cookie の値をキャッシュ キーに組み込みます。 URI が同じでも JSESSIONID 値が異なるアイテムは、一意のアイテムとして個別にキャッシュされます。

NginxはETagヘッダーを使用する

Nginx 1.7.3 以降では、ETag ヘッダーは If-None-Match を完全にサポートします。

Nginx がバイト範囲リクエストを処理する方法

ファイルがキャッシュ内で新しい場合、Nginx はバイト範囲要求を尊重し、アイテムの指定されたバイトのみをクライアントに提供します。ファイルがキャッシュされていない場合、またはファイルが古い場合、Nginx は元のサーバーからファイル全体をダウンロードします。

リクエストが 1 バイトの範囲に対するものである場合、Nginx はダウンロード ストリームでその範囲を検出するとすぐにその範囲をクライアントに送信します。リクエストで同じファイル内の複数のバイト範囲が指定されている場合、Nginx はダウンロードが完了するとファイル全体をクライアントに配信します。

ダウンロードが完了すると、Nginx はリソース全体をキャッシュに移動し、単一の範囲または複数の範囲を問わず、今後のすべてのバイト範囲要求がキャッシュからすぐに満たされるようにします。

Nginx がアップストリーム サーバーへのバイト範囲リクエストをサポートするには、アップストリーム サーバーがバイト範囲リクエストをサポートしている必要があることに注意してください。

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

Pragma:no-cache ヘッダーは、すべての中間キャッシュをバイパスしてオリジン サーバーに直接送信されるコンテンツを要求するためにクライアントによって追加されます。デフォルトでは、Nginx は Pragma ヘッダーをサポートしていませんが、proxy_cache_bypass ディレクティブを使用してその機能を設定できます。

場所 /images/ { 
  proxy_cache my_cache; 
  proxy_cache_bypass $http_pragma; 
  # ... 
}

Nginxはstale-while-revalidateとstale-if-errorのヘッダーと拡張Cache-Controlをサポートしていますか?

Nginx 1.11.10 以降でサポートされています。これらの拡張機能の機能:

Cache-Control HTTP ヘッダーを拡張して、現在更新中の場合に古いキャッシュされた応答を使用できるようにします。 Cache-Control HTTP ヘッダーの stale-if-error 拡張により、エラーが発生したときに古いキャッシュされた応答を使用できるようになります。これらのヘッダーは、上記の proxy_cache_use_stale ディレクティブよりも優先度が低くなります。

Nginx は Vary ヘッダーをサポートしていますか?

Vary ヘッダーは、Nginx 1.7.7 以降でサポートされています。

結論は

この時点で、Nginx プロキシ キャッシュがどのように機能し、適切に構成する方法について十分に理解しているはずです。ご質問やご意見がございましたら、お気軽にコメントを残してください。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Nginx リバース プロキシとキャッシュおよびキャッシュのクリア方法
  • nginx をプロキシ キャッシュとして使用する方法

<<:  react+reduxを使用してカウンター機能を実装すると発生する問題

>>:  RR および RC 分離レベルでのインデックスとロックのテスト スクリプトのサンプル コード

推薦する

CSS3の3D効果を使って立方体を作成する

CSS3 の 3D 効果を使用して立方体を作成する方法を学ぶと、3D シーンの回転と変位のプロパティ...

JS関数の継承について学ぶ記事

目次1. はじめに: 2. プロトタイプチェーン継承: 3. コンストラクタ継承の借用(オブジェクト...

momentJs を使用してカウントダウン コンポーネントを作成する (サンプル コード)

今日はvueとmomentで作ったカウントダウンを紹介したいと思います。具体的な内容は以下のとおりで...

process.env.NODE_ENV 本番環境モードを設定する方法

始める前に、process.env.NODE_ENV にはデフォルトで開発と本番の 2 つの状態しか...

React の調整アルゴリズム Diffing アルゴリズム戦略の詳細な説明

目次アルゴリズム戦略単一ノードの差分配列ノードの差分キー値の使用要件アルゴリズム戦略React の調...

JavaScript キャンバスでカラフルな太陽のハロー効果を実現

この記事では、カラフルな太陽のハロー効果を実現するためのJavaScriptキャンバスの具体的なコー...

ApacheとTomcatを組み合わせて静的状態と動的状態を分離する方法

実験環境ApacheとTomcatは両方ともIPアドレス192.168.153.136のホストにイン...

uniAppエディタWeChatスライド問題について

ユニアプリアプレットはWeChatでも同様のドロップダウン問題を抱えることになる解決策は、app.v...

JavaScript で二分探索木を実装する

JavaScriptでの検索二分木実装は参考までに。具体的な内容は以下のとおりです。バイナリ検索木 ...

Dockerとイメージの操作方法

ミラーを探すDocker Hubのウェブサイトからイメージを検索できます。Docker Hubのウェ...

Dockerコンテナの自動終了を停止する方法の詳細な説明

この記事では、Docker コンテナとフロントエンド プロセスの関係と、コンテナを永続的に実行できる...

Vue ベースの円形スクロールリスト機能を実装する

注: 親コンテナーに高さと :data='Array' および overfolw:h...

Vue3.0でカスタム命令を書くための簡単な手順

序文Vue には、v-if、v-bind、v-on などの豊富な組み込みディレクティブが用意されてい...

MySQLプリコンパイル機能の詳細な説明

この記事では、MySQLのプリコンパイル機能について紹介します。具体的な内容は以下のとおりです。 1...

CSS の border 属性と display 属性の使い方の簡単な分析

境界プロパティの概要borderプロパティは要素の境界を設定します。境界線の3要素は、太さ、線の種類...