ブログ | NGINX

NGINX と NGINX Plus による高性能キャッシュ

NGINX-F5 水平黒タイプ RGB の一部
オーウェン・ギャレット サムネイル
オーウェン・ギャレット
2016 年 8 月 24 日公開

高性能キャッシュウェビナーのプレゼンターの画像
この投稿は、Andrew Alexeev が紹介した Owen Garrett によるウェビナーを基に作成されています。

目次

導入

0:00 導入
1:22 このウェビナーについて
2:17 コンテンツキャッシュの基本原則
2:35 基本原則
3:59 HTTP キャッシュの仕組み
7:46 NGINX キャッシュとは何ですか?

コンテンツキャッシュとNGINX

9:55 NGINXの運用
10:06 NGINX 設定
11:14 キャッシュプロセス
15:32 キャッシュはHTTPだけではない
17:10 何が起こっているのか理解する方法
17:38 キャッシュインストルメンテーション
19:08 キャッシュインストルメンテーション(続き)
20:09 キャッシュステータス
21:57 NGINX におけるコンテンツ キャッシュの機能
22:40 仕組み
23:53 キャッシュされたコンテンツはどのように保存されますか?
26:36 ディスクからキャッシュをロード中
28:07 ディスクキャッシュの管理
29:22 ディスクからコンテンツを消去する

キャッシュの制御

31:27 キャッシュの制御
32:30 遅延キャッシュ
34:45 キャッシュ時間の制御
36:18 キャッシュする/しない
37:25 複数のキャッシュ
39:07 クイックレビュー – なぜキャッシュなのか?
39:44 ページ速度が重要なのはなぜですか?
40:46 Googleがルールを変えた
41:28 パフォーマンスの低下によるコスト
43:00 NGINXキャッシュを使用すると
45:21 終わりに

質疑応答

47:20 バイト範囲リクエスト
49:13 プロキシキャッシュの再検証
50:07 同等のディスクにキャッシュを分散する
50:50 ヘッダーの変更
51:25 キャッシュプリミティブ
51:52 アップストリームヘッダーとデータ
52:13 *‑エンコードヘッダー
52:56 スパイディ
53:15 ヴァリーヘッダー、第2ラウンド
53:45 ページスピード
54:00 その他のキャッシュ

0:00 はじめに

アンドリュー・アレクセエフ: 最新のウェビナーへようこそ。私の名前はアンドリューです。 NGINX は、世界中の Web サイトの実行速度を向上させ、応答性を高め、簡単に拡張できるようにするという理念のもと、Igor Sysoev によって作成されました。 現在、NGINX はインターネット上のトップ サイトの 30% 以上、すべての Web サイトの 20% 以上を支えています。[編集者注: これらの統計は、2014 年 5 月にウェビナーが実施された時点のものです。現在の値については、こちらをご覧ください。 ] このウェビナーの内容が、皆様の既存または計画中の NGINX 環境に役立ち、適用できることを願っています。

さて、オーウェン・ギャレットを紹介させてください。 Owen は、NGINX で製品開発を担当しています。今日、Owen は、NGINX の強力なキャッシュ メカニズムを適用して、アプリケーションを繰り返し同じコンテンツを生成する負担から解放する方法について説明します。

1:22 このウェビナーについて

オーウェン・ギャレット: アンドリューさん、ありがとうございました。皆さん、これから 45 分から 50 分間お付き合いいただき、本当にありがとうございました。 コンテンツ キャッシュに関して NGINX がどのように機能するかについて説明し、パフォーマンスを向上させる方法をいくつか見ていきます。また、コンテンツ キャッシュが実際にどのように機能するかを少し詳しく調べて、NGINX 内で何が起こっているかをデバッグおよび診断できるようにします。最後に、キャッシュ可能なコンテンツに対して NGINX が行う処理を非常に細かく制御できるように、いくつかの巧妙なヒントとコツを紹介します。

アンドリューが説明したように、すべて同じ根本的な目的を目指しており、反復的なコンテンツを生成する上流サーバーの負担を取り除き、ビジネスに本当に必要なアプリケーションを実行できるようにすることです。 これらのサーバーを超えて増加することで、エンドユーザーに優れたレベルのサービスを提供し、インターネットからのトラフィックの急増や上流サーバーの障害の可能性に対するホールとしてのサービスの信頼性を高めます。

2:17 コンテンツキャッシュの基本原則

NGINX の実装構成に入る前に、コンテンツ キャッシュが基本的にどのように機能するかを簡単に確認して、全員が同じページ、同じコア情報のベースラインから始められるようにしたいと思います。

2:35 基本原則

コンテンツ キャッシュの基本原則は、上流サーバーから反復的な作業をオフロードすることです。 最初のユーザーが Web サイト上のコンテンツ項目をリクエストすると (青いアイコンと青い線で示されています)、その HTTP リクエストは NGINX に転送され、そこから右側の灰色のアップストリーム サーバーに転送されます。

応答はリモート ユーザーに転送されますが、キャッシュ可能な場合 (その意味については後ほど説明します)、NGINX はその応答のコピーを保存します。 別のユーザー、つまりオレンジ色の男が同じコンテンツを要求すると、NGINX は上流サーバーからのリクエストを偽造するのではなく、ローカル キャッシュから直接コンテンツを提供できます。

キャッシュ可能で変更されないコンテンツを保存するというこの基本原則は、Web ブラウザー、CDN、アクセスしているサイト、CDN を活用するサイト、および他のデバイス上の NGINX によって使用されます。 これはリバース プロキシキャッシュとして動作し、通常はデータ センター内、または Web コンテンツや Web アプリケーションをホストしているオリジン サーバーの隣のクラウド上に展開されます。

3:59 HTTP キャッシュの仕組み

オリジン サーバーは、よく知られたいくつかの HTTP 応答ヘッダーの 1 つ以上を使用して、コンテンツのキャッシュ可能性を宣言します。 もちろん、キャッシュ サーバーはこの動作を無視するか、上書きするか、または変更することを選択できます。 しかし、構成されたコンテンツ キャッシュを理解するには、まず、オリジン サーバーがコンテンツがキャッシュ可能で、変更されず、[キャッシュされた] コピーに一定の有効期間があることを示す方法について十分に理解する必要があります。

コンテンツ キャッシュは、 Expiresと呼ばれる単純な HTTP 応答ヘッダーから始まりました。 オリジン サーバーは何らかのコンテンツを提示し、そのコンテンツがExpiresヘッダーの日付まで有効であると宣言します。 この方法は、より効果的で柔軟性の高い方法であるCache-Controlヘッダーにすぐに取って代わられました。

Expires は少々使いにくく、非効率的です。 日付は適切にフォーマットおよび解析される必要がありますが、 Cache-Control ははるかに合理化されており、コンテンツ キャッシュのニーズと速度に合わせて調整されています。 Cache-Control は、コンテンツをパブリックまたはプライベートとして宣言し、パブリックの場合は、キャッシュ オブジェクトがそのコンテンツを再要求するまでにキャッシュできる秒数であるmax-ageを宣言します。

キャッシュを直接制御する 3 番目のヘッダーはX-Accel-Expiresです。 このヘッダーは NGINX に特化しており、NGINX のみが理解します。このヘッダーは、上記のヘッダーの動作をオーバーライドし、コンテンツの項目をキャッシュする期間を NGINX に直接正確に伝える場合に使用されます。

ウェブブラウザにコンテンツを長期間キャッシュさせたいが、プロキシ キャッシュ (オリジン サーバーの前面にある NGINX) にコンテンツを短期間キャッシュさせたい場合があります。これにより、変更がより迅速に反映され、新しいクライアントにプッシュされ、古いクライアントは必要がないときにコンテンツを再要求し続けることがなくなります。

ただし、このメソッドは最後の 2 つのヘッダーを使用して実装することもできます。 オリジン サーバーは、コンテンツの項目が最後に変更された日時を宣言でき、 ETag (エンティティ タグ) と呼ばれるものを宣言できます。ETag は、そのコンテンツを識別する不透明な文字列 (多くの場合ハッシュ値) です。

クライアントは条件付きGETを使用してリクエストを行うことができます。 リクエストにIf-Modified-SinceまたはIf-None-Matchヘッダーを含めることができます。 そうすることで、クライアントは、特定の日付に最後に変更されたコンテンツ、または特定のETagを持つコンテンツのキャッシュされたバージョンがあることを宣言します。 サーバーが保持している最新バージョンがクライアントのバージョンと一致する場合、サーバーは単に304変更されていません。 これは高速応答であり、ネットワーク帯域幅を節約し、クライアントがキャッシュされたコンテンツのコピーがまだ有効かどうかを自由に確認できるようにします。

これら 5 つのヘッダーは、オリジン サーバーの観点から、コンテンツがキャッシュ可能であるかどうか (有効性、鮮度、およびETagの観点から、コンテンツ自体の詳細) を定義します。

7:46 NGINX キャッシュとは?

NGINX などのプロキシ キャッシュは、それらのヘッダーにどの程度厳密に準拠するかを比較的自由に解釈できます。 明らかに、キャッシュできないものをキャッシュすべきではありませんが、元のサーバーがキャッシュ可能であると言っている場合は、キャッシュする義務はありません。

NGINX の基本的な動作は、応答にSet-Cookieヘッダーがない場合、オリジン サーバーによってキャッシュ可能と示されたすべてのGETおよびHEAD要求をキャッシュすることです。 これは、 Set-Cookieヘッダーには通常、各リクエストに固有の一意のデータが含まれており、デフォルトではその値をキャッシュすることは適切ではないためです。

NGINX は、特定のキー (キャッシュ キー) によって各リソースをキャッシュします。 同じキャッシュ キーを生成するすべてのリクエストは、同じリソースで満たされます。 デフォルトでは、キャッシュは生の URL にマッピングされますが、構成では、このスライドに示されている文字列 [ $scheme$proxy_host$uri$is_args$args ] にマッピングされます。 NGINX がコンテンツをキャッシュする時点で、[有効期間] は、 X-Accel-Expiresヘッダー (存在する場合)、またはCache-Controlヘッダー、または従来のExpiresヘッダーによって (優先順位に従って) 定義されます。

NGINX を調整して、これらのヘッダーの一部をマスクしたり、元のサーバーの情報にまったく関係なく、代わりに固定のキャッシュ時間を提供したりすることができます。 参考までに、 RFC 2616 では、 HTTP に関するプロキシ キャッシュの望ましい動作が定義されています。

これにより、キャッシュの普遍性と、Web サイトを高速化し、オリジン サーバーの負荷を軽減するために、キャッシュしても通常は安全なコンテンツをキャッシュする際の NGINX の基本的なデフォルト動作について簡単に理解できるようになります。

9:55 NGINXの運用

それでは、NGINX の動作を少し見てみましょう。 コンテンツ キャッシュを有効にするように NGINX を構成するのは非常に簡単です。

10:06 NGINX 構成

これは、NGINX 構成ファイル内の数行です。そのうちの 1 行は、ファイルのレイアウト方法、[そのキャッシュ内のオブジェクトの] 有効期限、およびそのキャッシュのサイズを宣言する特定のパラメータ セットを使用してディスク上にキャッシュを作成するためのものです。 次に、2 番目のproxy_cacheディレクティブは NGINX プロキシに関連付けられ、コンテンツ (結果、応答) を名前付きキャッシュにキャッシュするように指示します。

ここでは、 oneというキャッシュを 1 つ作成しました。メタデータのメモリサイズは 10 MB ですが、キャッシュされるコンテンツのディスク上のサイズは無制限です。 コンテンツはキャッシュされ、60 分間非アクティブだった場合に取得されます。 そのキャッシュはoneと呼ばれ、デフォルト サーバーによって使用されます。 これら 2 つの [ディレクティブ]、 proxy_cache_pathproxy_cache は、NGINX のプロキシ サーバーで信頼性が高く一貫性のあるキャッシュを有効にするのに十分です。

11:14 キャッシュプロセス

NGINX がリクエストを受信してキャッシュを照会するときに実行されるプロセスは、次のように定義されます。 まず、リクエストを読み取り (このスライドの左上のボックス)、キャッシュ キーを生の URI に組み立て、そのリクエストに対応するリソースを識別するために使用するその他のパラメーターを作成します。 次に、メモリ内のメタデータにアクセスしてディスク上のキャッシュをチェックし、そのリクエストに対する応答の有効な最新のコピーがあるかどうかを確認します。

もしそうなら、それはヒットとしてカウントされます。 その後、NGINX はキャッシュから直接応答できます。 NGINX が静的コンテンツを提供するのとまったく同じように、ディスクからコンテンツを提供することでキャッシュから応答します。 そのため、NGINX が設計されたレベルのパフォーマンス、信頼性、スケーラビリティが得られます。 静的コンテンツの場合、NGINX のコンテンツ キャッシュからコンテンツを提供すると、まったく同じレベルの [パフォーマンス] が得られます。

一方、キャッシュをチェックすると、キャッシュミスが発生する可能性があります。 これは、キャッシュ内にコンテンツがないか、キャッシュ内のコンテンツが古くなっており、更新する必要があることを意味します。 最も単純なケースでは、そのミスは、元のサーバーからそのコンテンツを要求し、応答を受信して、キャッシュ可能かどうかを確認することを意味します。

そうであれば、プロキシ モードで処理される大きな応答に対して NGINX が行うのと同様に、ディスクにストリーミングします。 その後、応答がディスクにストリーミングされると、それをキャッシュにコピーし、キャッシュから直接応答します。 このアプローチの課題の 1 つは、NGINX が同じコンテンツに対して同時に複数のリクエストを受信し、すべてが失敗に終わることです。

NGINX は通常、これらのリクエストをすべて元のサーバーに転送するため、特に応答の生成に長い時間がかかるリクエストの場合は、サーバーに過負荷がかかる可能性があります。 そのため、キャッシュ ロックを使用できます。 proxy_cache_lockディレクティブは、コンテンツの一部が更新される場合に、一度に 1 つのリクエストのみがアップストリーム サーバーに送信されるようにします。

したがって、私が説明したシナリオでは、最初のリクエストはアップストリーム サーバーに送信されますが、同じコンテンツに対する残りのリクエストは、応答が提供されてキャッシュに挿入される (この時点ですべてのリクエストを満たすことができます) か、タイムアウト ( proxy_cache_lock_timeoutディレクティブによって設定) に達するまで保留されます。NGINX は、コンテンツがサーバーから返されるのに十分長い時間待機し、その時点で、解放したリクエストはオリジン サーバーに転送されます。

したがって、 proxy_cache_lockとタイムアウトを使用すると、同じコンテンツに対するリクエストが多数あるビジー状態のサイトの場合、そのコンテンツがキャッシュ内で期限切れになっても、複数のリクエストによってオリジン サーバーが突然過負荷にならないようにするための強力な制御が可能になります。

NGINX のキャッシュ プロセスには、チャートのほぼすべての段階をカバーしているため、このフローチャートにきれいに収まらないもう 1 つの要素があります。 これは、 proxy_cache_use_staleディレクティブで設定される機能です。 いつでも、これらのステージのいずれかが何らかの理由で失敗した場合、たとえば、コンテンツを更新しているときにタイムアウトになったり、上流サーバーから不正な応答が返されたり、その他の種類のエラーが発生したりした場合は、キャッシュされたコンテンツが古くても、キャッシュから直接応答するオプションがあります。

これは、上流サーバーがトラフィックで圧倒されたり、メンテナンスや壊滅的なエラーのために障害が発生した場合に非常に強力なツールです。 これにより、NGINX はクライアントにエラー メッセージを返すのではなく、キャッシュ内の古いコンテンツを使用してコンテンツを配信し続けることができるようになります。

15:32 キャッシュはHTTPだけではない

NGINX でのキャッシュは HTTP だけのものではありません。 NGINX は、リクエストを上流の Web サーバーに転送する単なる HTTP プロキシではありません。 通常、これらのアップストリーム Web サーバーは、FastCGI や SCGI などの API とインターフェイスするために存在します。NGINX は、HTTP プロキシと非常によく似たプロキシ形式でこれを直接実行できます。

NGINX は、 HTTP プロキシFastCGI プロキシuWSGI プロキシ、およびSCGI プロキシにキャッシュ技術を採用できます。 これらはすべて、HTTP プロキシとほぼ同じ方法で動作し、キャッシュはディスクに保存され、応答が直接返されるため、これらのアップストリーム サービスへのプロキシが不要になります。

NGINX は memcached サーバーとインターフェースすることもできます。これは少し異なるキャッシュ アプローチです。 この場合、NGINX はコンテンツを直接保存せず、memcached をプロキシとして使用し、外部エージェントを利用して memcached に必要なコンテンツを入力します。 これはもう 1 つの便利なツールであり、必要に応じて外部サイトから memcached にデータを入力する方法はたくさんあります。 したがって、それがビジネス要件である場合、これを NGINX のキャッシュをシードする方法と見なすことができます。

17:10 何が起こっているのか理解する方法

複数の層を持つ大規模なインフラストラクチャがあり、キャッシュを実行する層と実行しない層、コンテンツを生成する層と生成しない層がある場合、キャッシュは非常に複雑になる可能性があります。その場合、何が起こっているのか(コンテンツの出所)を追跡し、発生した問題を診断してデバッグするのは非常に困難です。 NGINX では、できるだけ簡単にできるようにしています。

17:38 キャッシュインストルメンテーション

洗練されたインストルメンテーションを使用すると、インストルメンテーションを動的に制御して、コンテンツの取得元、キャッシュ内の保存場所、キャッシュ内のステータスを追跡できます。

最初のステップは$upstream_cache_status変数です。これは、キャッシュからのものであるかどうかに関係なく、NGINX が応答した各リクエストに対して計算されます。 そして、 add_headerディレクティブを使用して、その変数の値を継続的に応答に追加します。 従来、その値はレスポンスのX-Cache-Statusヘッダーに格納されます。 7 つの異なる値のいずれかを取り、そのコンテンツがどのように提供されたかを宣言します。 キャッシュをバイパスしたかどうか、再検証から来たかどうか、ヒットしたかどうか。

これは、あなたの反応がどこから来ているのかを理解するための最初のステップです。 それらはローカル NGINX キャッシュから来ているのでしょうか、それともアップストリーム サーバーから来ているのでしょうか? また、その応答ヘッダーは、さまざまな方法で検査できます。たとえば、 curlなどのツールを使用してコマンドラインから検査したり、非常に一般的には、対話型デバッガーを使用して Web ブラウザーで検査したりできます。

もちろん、その値をすべてのエンドユーザーに対して宣言したくない場合もあります。 ヘッダー応答にその値を挿入するタイミングについては、選択的に行う必要があります。

19:08 キャッシュインストルメンテーション(続き)

NGINX の設定言語により、選択する柔軟性が得られます。 この例は、これを実行できる多くの方法のうちの 1 つを示しています。 リモート アドレスを取得し、それが localhost である場合は、 $upstream_cache_status を一時変数 ( $cache_status ) に格納します。 最後に、レスポンスを返すときに、レスポンスに一時変数を入れます。

この方法では、選択された IP アドレスからのリクエストのみが$upstream_cache_status変数の値を確認します。 他にもいろいろなことができます。コンテンツがディスク上にどのように保存されるかについては後ほど説明します。 ディスク上の場所を計算するために使用されるキーを応答に入れることができます。 実行中のキャッシュを診断するために、応答にあらゆる種類のパラメータを入れることができます。

20:09 キャッシュステータス

NGINX の商用バージョンであるNGINX Plus は、キャッシュなどのユースケースに役立つ多数の追加機能を提供します。 NGINX Plus は、モスクワのエンジニアリング チームによって構築され、正しい動作を保証するために広範な回帰テストが実行されている、商用サポートされている NGINX ビルドです。

NGINX Plus には、NGINX をリバース プロキシやロード バランサーとして使用したい企業を対象とした機能も多数含まれています。 負荷分散、ヘルスチェック、高度なビデオストリーミングに関する機能。 そしてこれに関連して、拡張ステータス、より優れた診断、NGINX で何が起こっているかの視覚化に関する機能があります。

[編集者注 – 上記のスライドと次の段落は、 NGINX Plus APIを参照するように更新されました。NGINX Plus API は、ここで最初に説明した個別のステータス モジュールを置き換え、廃止します。]

デモについては、 demo.nginx.com/dashboard.htmlにアクセスすると、 NGINX Plus API を使用して NGINX Plus から公開されたステータス データを表示する Web ページが表示されます。また、指定されたcurlコマンドを実行すると、NGINX Plus バイナリから直接取得された生の JSON データが表示されます (ここでは、各要素を独自の行に配置し、階層的にインデントするためにjqユーティリティにパイプされています)。

この JSON データには、NGINX Plus デプロイメント内の各キャッシュの状態に関するリアルタイム データが含まれています。 これは、 $upstream_cache_status変数やキャッシュを計測できる他の方法と併せて、NGINX がコンテンツをキャッシュする方法の概要を非常によく示し、個々のリクエストをドリルダウンして、そのリクエストがキャッシュからのものであるかどうか、およびキャッシュ内の現在のステータスを把握できるようにします。

21:57 NGINX におけるコンテンツ キャッシュの機能

さて、外部からコンタクト キャッシュを調べる方法を見てきましたが、次は内部から見てみましょう。 NGINX 内ではどのように機能しますか? 前述したように、NGINX のコンテンツ キャッシュは、ディスク上のファイルが処理されるのとほぼ同じように機能します。 コンテンツ キャッシュからコンテンツを提供する場合も、静的コンテンツを提供する場合と同じパフォーマンス、同じ信頼性、同じオペレーティング システムの最適化が得られます。これは、NGINX が定評のあるパフォーマンスです。

22:40 仕組み

コンテンツ キャッシュは永続キャッシュとしてディスクに保存されます。 オペレーティング システムと連携してディスク キャッシュをメモリにスワップし、メモリに保存するコンテンツに関するヒントをオペレーティング システムのページ キャッシュに提供します。 つまり、キャッシュからコンテンツを提供する必要がある場合、非常に迅速に提供できるということです。

キャッシュに関するメタデータ、つまりキャッシュの内容とその有効期限に関する情報は、すべての NGINX プロセスにわたる共有メモリ セクションに個別に保存され、常にメモリ内に存在します。 そのため、NGINX はキャッシュをクエリし、キャッシュを非常に高速に検索できます。応答を取得してエンド ユーザーに返す必要がある場合にのみ、ページ キャッシュにアクセスする必要があります。

コンテンツがキャッシュに保存される方法、起動時に永続キャッシュが空の NGINX ワーカー プロセスにロードされる方法、NGINX がキャッシュに対して自動的に行うメンテナンスの一部、そして最後に、特定の状況でキャッシュからコンテンツを手動で削除する方法を説明します。

23:53 キャッシュされたコンテンツはどのように保存されますか?

コンテンツ キャッシュはproxy_cache_pathというディレクティブを使用して宣言されることを思い出してください。 このディレクティブは、ファイル システム上でキャッシュが保存される場所、キャッシュの名前、メタデータのメモリ内のキャッシュのサイズ、およびディスク上のキャッシュのサイズなど、パラメータの数を指定します。 この場合、ディスク上に 40 MB のキャッシュがあります。

コンテンツがどこに保存されているかを理解するための鍵は、キャッシュ キー (NGINX がキャッシュ可能な各リソースに割り当てる一意の識別子) を理解することです。 デフォルトでは、その識別子はリクエストの基本パラメータ(スキーム、ホストヘッダー、URI、および任意の文字列引数)から構築されます。

ただし、必要に応じて、Cookie 値や認証ヘッダー、あるいは実行時に計算した値などを使用して拡張できます。 英国のユーザー用と米国のユーザー用に異なるバージョンを保存したい場合もあります。 これらはすべて、 proxy_cache_keyディレクティブを構成することで可能になります。

NGINX はリクエストを処理するときにproxy_cache_keyを計算し、その値から MD5 の合計を計算します。 スライドの下に示したコマンド ラインの例を使用して、これを自分で再現できます。 キャッシュ キーhttplocalhost:8002/time.phpを取得し、それをmd5sumに渡します。 シェルからこれを行うときは、新しいラインもポンプで送り込まないように注意してください。

これにより、キャッシュ可能なコンテンツに対応する MD5 ハッシュ値が計算されます。 NGINX はそのハッシュ値を使用して、コンテンツを保存するディスク上の場所を計算します。 proxy_cache_pathでは、1 文字のディレクトリと 2 文字のディレクトリを使用して 2 レベルのキャッシュを指定していることがわかります。 文字列の末尾からこれらの文字を抜き出して、4 9bというサブディレクトリを作成し、キャッシュの内容 (およびヘッダーと少量のメタデータ) をディスク上のファイルにドロップします。

コンテンツのキャッシュをテストできます。 キャッシュ キーを応答ヘッダーの 1 つとして出力し、それをmd5sumに渡してその値のハッシュ対応を計算することができます。 次に、ディスク上の値を調べて、それが実際に存在するかどうかを確認し、NGINX がキャッシュしたヘッダーを確認して、これらすべてがどのように組み合わされているかを理解できます。

26:36 ディスクからキャッシュをロード中

コンテンツがディスクに保存され永続的になったので、NGINX の起動時にそのコンテンツをメモリに読み込む必要があります。つまり、ディスク キャッシュを調べてメタデータを抽出し、各ワーカー プロセスが使用する共有メモリ セグメントのメモリにメタデータを読み込む必要があります。 これは、キャッシュ ローダーと呼ばれるプロセスを使用して行われます。

キャッシュ ローダーは起動時に起動し、一度実行されて、メタデータを小さなチャンクでディスクに読み込みます。 一度に 100 個のファイルを 200 ミリ秒にサンドボックス化し、その間に 50 ミリ秒間一時停止し、キャッシュ全体を処理して共有メモリ セグメントにデータを入力するまでこれを繰り返します。

その後、キャッシュ ローダーは終了し、NGINX が再起動または再構成され、共有メモリ セグメントを再初期化する必要がある場合を除き、再度実行する必要はありません。 キャッシュ ローダーの動作を調整できます。これは、ディスクが非常に高速で負荷が軽い場合に適している可能性があります。 大量のファイルと低速ディスクを含むキャッシュを保存していて、NGINX の起動時にキャッシュ ローダーが過剰な量の CPU を使用することを望まない場合は、実行速度を速くしたり、少し遅くしたりすることもできます。

28:07 ディスクキャッシュの管理

キャッシュがメモリ内に保存され、ファイルがディスクに保存されると、アクセスされないキャッシュされたファイルが永久に残ってしまうリスクがあります。 NGINX は最初にファイルを見つけたときにそれを保存しますが、ファイルに対するリクエストがなくなった場合、何かが起こってファイルを削除するまで [ファイル] はディスク上にそのまま残ります。

これはキャッシュ マネージャーです。定期的に実行され、一定期間アクセスされていないファイルをディスクから消去し、キャッシュが大きすぎて宣言されたサイズをオーバーフローした場合にファイルを削除します。 最近使用されていない順に削除されます。 キャッシュ ローダーを設定するのと同じように、 proxy_cache_path [ディレクティブ] のパラメータを使用してこの操作を設定できます。

  • 非アクティブ時間はデフォルトで 10 分に設定されます。
  • max-sizeパラメータにはデフォルトの制限はありません。 キャッシュに最大サイズの制限を課すと、その制限を超えることがありますが、キャッシュ マネージャーが実行されると、最近使用されていないファイルが削除され、制限内に戻ります。

29:22 ディスクからコンテンツを消去する

最後に、ディスクからコンテンツを消去したい場合もあります。 ファイルを見つけて削除したい場合、前に説明した手法( md5sumでキャッシュ キーを実行する、またはファイル システム全体で再帰grep を実行して削除する必要のあるファイルを特定する)を知っていれば、比較的簡単に実行できます。

あるいは、NGINX Plus を使用している場合は、その製品に組み込まれているキャッシュ パージ機能を使用できます。 キャッシュ パージ機能を使用すると、リクエストから特定のパラメータを取得できます。通常、キャッシュ パージ リクエストであることを識別する方法として、 PURGEと呼ばれるメソッドを使用します。

パージは、URI を検査し、その URI に一致するすべてのファイルをキャッシュから削除する特別な NGINX Plus ハンドラーによって処理されます。 URI にアスタリスクを付加して語幹にすることができます。 この場合、purge 機能を使用して、localhost ホスト ポート 8001 から提供されるすべてのファイルを削除しますが、もちろんサブディレクトリも配置できます。

どちらの方法を使用する場合でも、いつでもディスク上のキャッシュからファイルを削除したり、キャッシュ ディレクトリ全体をrm -rf したりしてもまったく問題ありません。 NGINX は処理を中断することなく、ディスク上のファイルの存在を継続的に確認します。 これらが欠落している場合は、キャッシュ ミスが発生します。 その後、NGINX は元のサーバーからキャッシュを取得し、それをディスク上のキャッシュに保存します。 したがって、キャッシュから個々のファイルを消去する必要がある場合でも、常に安全で信頼性が高く、安定しています。

31:27 キャッシュの制御

そこで、キャッシュの仕組みと NGINX 内の実装を確認し、静的コンテンツで得られるのと同じ種類のパフォーマンスを実現するためにディスク上にファイルを保存する方法について詳細に調べました。 それでは、キャッシュについてもう少し詳しく見ていきましょう。

シンプルなサイトの場合、キャッシュをオンにすると、通常、必要なレベルのパフォーマンスとキャッシュ動作を維持するために必要な処理が正確に実行されます。 しかし、最適化を行う必要は常にあり、デフォルトの動作が希望する動作と一致しない状況もしばしばあります。

おそらく、オリジン サーバーが正しい応答ヘッダーを設定していないか、NGINX 自体の内部で指定されている内容を上書きしたい可能性があります。 NGINX を設定してキャッシュの動作を微調整する方法は無数にあります。

32:30 遅延キャッシュ

キャッシュを遅延することができます。 大量のコンテンツがあり、その多くが 1 時間または 1 日に 1 回か 2 回しかアクセスされない場合、これは非常に一般的な状況です。 その場合、ほとんどの人が読まない会社のパンフレットがあれば、そのコンテンツをキャッシュしようとするのは時間の無駄になることが多いです。 遅延キャッシュを使用すると、透かしを配置できます。 一定回数リクエストされた場合にのみ、このコンテンツのキャッシュされたバージョンが保存されます。 proxy_cache_min_usesのウォーターマークに達するまで、バージョンはキャッシュに保存されません。

これにより、キャッシュに入れるコンテンツをより細かく区別できるようになります。 キャッシュ自体は限られたリソースであり、通常はサーバーにあるメモリの量によって制限されます。これは、キャッシュが可能な限りメモリにページングされるようにする必要があるためです。 そのため、特定の種類のコンテンツを制限し、人気のあるリクエストのみをキャッシュに格納したい場合がよくあります。

キャッシュ再検証は、NGINX Open Source と NGINX Plus に最近追加された機能です。 これは、 If-Modified-Since機能を変更して、NGINX がキャッシュされた値を更新する必要がある場合に、そのコンテンツの新しいバージョンを取得するために単純なGETを行うのではなく、「この特定の日時に変更されたキャッシュ バージョンがあります」という条件付きのGET を行うようにします。

オリジンサーバーは次のように応答するオプションがあります。304変更されていません。つまり、現在お持ちのバージョンが、現在も最新のバージョンであることを意味します。 これにより、アップストリーム帯域幅が節約され、元のサーバーは変更されていないコンテンツを再送信する必要がなくなり、ディスク書き込みも節約される可能性があります。 NGINX は、そのコンタクトをディスクにストリーミングし、それを所定の位置にスワップして、古いバージョンを上書きする必要はありません。

34:45 キャッシュ時間の制御

コンテンツをキャッシュする期間を細かく制御できます。 多くの場合、オリジン サーバーは、ブラウザーに適したキャッシュ ヘッダー (コンテンツの更新要求が比較的頻繁に発生する長期キャッシュ) を使用してコンテンツを提供します。 ただし、変更をより迅速に取得するために、NGINX プロキシをオリジン サーバーの直前に配置して、ファイルをより頻繁に更新することもできます。

ブラウザのキャッシュ タイムアウトを 60 秒から 10 秒に短縮すると負荷が大幅に増加しますが、NGINX のキャッシュ タイムアウトを 60 秒から 10 秒に延長すると負荷はわずかにしか増加しません。 リクエストごとに、オリジン サーバーに 1 分あたり 5 件のリクエストが追加されますが、リモート クライアントの場合は、サイト上で同様のアクティビティを実行しているクライアントの数によって決まります。

したがって、オリジン サーバーのロジックと意図をオーバーライドできます。 特定のヘッダーをマスクしたり、NGINX に無視するように指示したりできます。 X-Accel-ExpiresCache-Control 、またはExpires 。 また、NGINX 設定のproxy_cache_validディレクティブを使用して、デフォルトのキャッシュ時間を指定することもできます。

36:18 キャッシュする/しない

場合によっては、オリジン サーバーがキャッシュ可能としているコンテンツをキャッシュしない場合や、NGINX に保存されているコンテンツのバージョンをバイパスするようにしたい場合があります。proxy_cache_bypass およびproxy_no_cacheディレクティブ使用すると、その程度の制御が可能になります。

これらをショートカットとして使用すると、HTTP 認証などの特定のリクエスト ヘッダー セットが設定されている場合や、リクエスト パラメーターが存在する場合に、キャッシュをバイパスして、NGINX のキャッシュを自動的に更新するか、完全にスキップして常にオリジン サーバーから取得するかを指定できます。

通常、これらはかなり複雑なキャッシュの決定のために行われ、Cookie と認証ヘッダーの値についてきめ細かい決定を行って、何をキャッシュするか、何をオリジン サーバーから常に受信するか、何を NGINX キャッシュに保存しないかを制御します。

37:25 複数のキャッシュ

最後に、非常に大規模な展開の場合、いくつかの理由から、個々の NGINX インスタンス内で複数のキャッシュを調べる必要がある場合があります。 サイトの性質やそのサイトのパフォーマンスの重要性に応じて、さらには共有ホスティングの状況で各テナントがサインアップしている特定のプランに応じて、NGINX プロキシ上のテナントごとに異なるキャッシュ ポリシーを設定できます。

または、NGINX ホストに複数のディスクがある場合、各ディスクに個別のキャッシュを展開するのが最も効率的です。 黄金律は、あるディスクから別のディスクへのコピーの数を最小限に抑えることです。これは、各ディスクにキャッシュを固定し、そのキャッシュを使用する各プロキシの一時ファイルを正しいディスクに固定することで実現できます。

標準的な操作では、NGINX は上流プロキシからコンテンツを受信すると、コンテンツが十分に小さくメモリに収まらない限り、そのコンテンツをディスクにストリーミングします。 その後、そのコンテンツがディスクにストリーミングされると、キャッシュに移動されます。 一時ファイルのキャッシュ上の場所 (一時ファイルが保存されているディスク) がキャッシュが保存されているディスクと同じである場合、その操作ははるかに効率的になります。

39:07 クイックレビュー – なぜキャッシュなのか?

ここまで、キャッシュについて、NGINX が使用する方法、NGINX 内での実装、そしてそれを調整する方法について説明しました。 終わりが近づいてきましたので、そもそもコンテンツをキャッシュする理由を簡単に振り返ってみましょう。 NGINX は世界中で 1 億 1,400 万の Web サイトに導入されており、これらのユーザーの多くは、Web アクセラレーションとコンテンツ キャッシュ機能のために NGINX を導入しています。[編集者注: この統計は、ウェビナーが 2014 年 5 月に配信された時点のものです。]

39:44 ページ速度が重要な理由

これらの機能により、Web サイトの速度が向上し、エンド ユーザーのエクスペリエンスが向上します。Web ページの速度は非常に重要です。 アナリストは長年にわたり、ユーザーの行動を監視し、俗に「N 秒ルール」と呼ばれるものを考案してきました。 これは、平均的なユーザーが、退屈してイライラし、別の Web サイト、競合他社の Web サイトに移動する前に、ページの読み込みとレンダリングを待つ準備ができている時間です。

基準が向上し、ユーザーの期待がますます高まるにつれて、ユーザーが待つ準備ができている期間はますます短くなっています。 少し疑わしい計算をすれば、それを推測して、2016 年頃までにユーザーの忍耐力がマイナスレベルになるだろうと結論付けることができます。

40:46 Googleがルールを変えた

しかし実際には、テクノロジーが私たちを追い越してしまいました。 Google は数年前、Google インスタント検索を導入したときにこれを図解しました。 Google では、検索ボックスに検索語を入力すると、入力が完了する前でも、候補となる検索結果が表示されます。 これは、現代のインターネットに対する期待の大きな変化を示しています。 Google 自身が述べているように、「ユーザーは、Web ページが本のページをめくるのと同じように反応することを期待しています」 – つまり、本のページをめくるのと同じように、素早く、シームレスに、滑らかに反応することを期待しています。

41:28 パフォーマンスの低下によるコスト

そのレベルのパフォーマンスを達成できない場合、Web サイトまたは Web サービスに関連付ける KPI に大きな影響が出る可能性があります。 広告のクリックスルー率: Google 自身も、検索ページの読み込みに 0.5 秒長くかかると、広告のクリックスルー率が 20% 低下することを発見しました。 収益の場合: 遅いウェブページの影響を意図的に調査する試みとして、Amazon はページの読み込みを意図的に 100 ミリ秒の倍数で増加させ、影響を受けた顧客からの収益が通常 100 ミリ秒の増加ごとに 1% 減少することを発見しました。

他の多くのアナリスト、ウェブサイト、調査員も、ページ滞在時間や直帰率など、ウェブサイトの指標に同様の影響があると報告しています。 最近、Google は検索結果のページランクを計算する際にページ速度を考慮し始めました。 重要なのは、最初のバイトまでの時間であるようです。 ページの読み込みの最初のバイトを取得するのにかかる時間が長くなるほど、ページランクへのペナルティが大きくなります。 ウェブサイトが Google 検索結果の 3 ページ目、4 ページ目、または 5 ページ目に表示されるため、アクセスすらされないという状況に陥ることがあります。

43:00 NGINXキャッシュで

NGINX のキャッシュ機能を使用すると、最初のバイトまでの時間を短縮し、Web コンテンツの応答性と応答性を高めることで、エンドユーザー エクスペリエンスを向上させることができます。

NGINX を使用すると、Web インフラストラクチャを統合および簡素化できます。 NGINX は単なるスタンドアロンの Web キャッシュではありません。 NGINX には Web オリジン サーバーが含まれており、FastCGI などの API への直接ゲートウェイが含まれています。また、NGINX Plus には、洗練されたエンタープライズ対応のロード バランサーとアプリケーション配信コントローラーを構築する機能が含まれています。 これにより、Web インフラストラクチャ内の複数の異なるネットワーク コンポーネントを単一のコンポーネント (NGINX または NGINX Plus) に統合できるため、信頼性が高く、デバッグが容易で、高速なソリューションが実現します。

NGINX を使用すると、上流サーバーから反復的なタスクを取り除くことで、サーバーの容量を増やすことができます。 実際、キャッシュできないように見えるコンテンツ(たとえば、ブログ サイトのフロント ページ)であっても、NGINX プロキシで 1 秒間だけキャッシュすることにはメリットがあります。

100 人のユーザーが同じ秒間に同じコンテンツをリクエストすると、NGINX はそれをオリジン サーバーへの 1 つのリクエストに減らし、コンテンツが 1 秒以上古くなることがないことを保証しながら、キャッシュからユーザーにコンテンツを返します。 これは、ブログ サイトや同様の Web サイトには十分すぎるほどですが、上流サーバーの負荷と十分な容量の管理と展開にかかる費用の両方において、パフォーマンスに大きな違いが生じます。

最後に、NGINX の戦略的な用途の 1 つである、プロキシ キャッシュの「古いデータを使用する」機能によって上流サーバーの障害からユーザーを保護するという点も忘れないでください。 動作が遅い場合、エラーが返される場合、何らかの障害がある場合、NGINX はコンテンツのローカル キャッシュ バージョンにフォールバックし、アップストリーム サーバーが回復するまでそれを使い続けることができます。

45:21 終わりに

世界で最もアクセス数の多いウェブサイトの 38% が、主にウェブ アクセラレーションとコンテンツ キャッシュ機能のために NGINX を使用しています。[編集者注: この統計は、2014 年 5 月にウェビナーが実施された時点で適用されたものです。現在の値はこちら で確認できます。 ] その他のソリューションと詳細については、NGINX と NGINX Plus の機能について説明しているnginx.comのブログと機能概要をご覧ください。 また、ウェビナー リストをご覧ください。今後のウェビナーだけでなく、このシリーズの過去のイベントから間もなく追加されるウェビナーも含まれています。

これらの機能をさらに詳しく調べたい場合は、もちろんnginx.orgnginx.comでドキュメントやソリューションを見つけることができますが、ダウンロードして試してみるのに勝るものはありません。 オープンソース製品はnginx.orgで入手できます。また、追加の負荷分散、アプリケーション配信、管理、使いやすさの機能を備えた商用サポート製品はnginx.comで入手できます。

皆さん、お時間を割いてご注目いただき、誠にありがとうございました。 このプレゼンテーションと NGINX でのコンテンツ キャッシュの概要が、多くの方にとって有益で啓発的なものであったことを願っています。

質疑応答

質問に回答して、結果を見てみましょう。

47:20 バイト範囲リクエスト

バイト範囲リクエストについて質問があります。 バイト範囲リクエストは、クライアントがコンテンツの一部をリクエストしたが、そのコンテンツのサブセットのみが必要な場合に使用されます。 たとえば、ビデオ ファイルがあり、クライアントはビデオの一部だけを必要としているとします。 または、非常に一般的なのは PDF ファイルです。ユーザーは PDF ファイルのインデックスを含むヘッダーを読み取り、クライアントは特定のページセットをダウンロードしたいだけです。 NGINX のコンテンツ キャッシュではどのように機能するのでしょうか?

手順は以下のとおりです。 NGINX がリソースのバイト範囲要求を受信し、リソース全体がすでにキャッシュ内にある場合、NGINX はクライアントが要求したバイト範囲でキャッシュから応答します。 そのリソースがキャッシュにない場合、NGINX はリソース全体をアップストリーム サーバーに要求し、そのリソースをキャッシュに保存します。 現在、その時点で NGINX はバイト範囲リクエストに従わず、リソース全体をクライアントに返します。 ほとんどの場合、それは許容できる行動です。

たとえば、クライアントが PDF ドキュメントをダウンロードしている場合、その最初のリクエストはいずれにしてもドキュメント全体に対するものとなり、そのドキュメントがストリーミングされる場合にのみ、クライアントは接続を中止し、バイト範囲のリクエストを開始します。 したがって、キャッシュされたコンテンツの場合、NGINX はバイト範囲リクエストを尊重します。 キャッシュされていないコンテンツの場合、NGINX はアップストリーム サーバーからコンテンツ全体を取得し、その 1 つのインスタンスでコンテンツ全体をクライアントに返します。

49:13 プロキシ キャッシュの再検証

これはプロキシ キャッシュの再検証機能に関する質問です。 これは、NGINX がアップストリーム サーバーに条件付きGET を実行して、コンテンツが変更されたかどうかを確認できるようにする機能です。 質問は次のとおりです:

プロキシ キャッシュの再検証ではETagが考慮されますか、それともコンテンツのIf-Modified-Since日付だけが考慮されますか?

答えは、コンテンツのIf-Modified-Since の日付をチェックするだけであり、実践としては、応答には常にIf-Modified-Sinceを含め、 ETagはオプションとして扱うのが一般的に良い方法です。これは、応答で処理する「最終更新日」ほど一貫して、または広く処理されないためです。

50:07 同等のディスクにキャッシュを分散する

NGINX が、単一のサイトのキャッシュをいくつかの同等のディスク間で負荷分散して、最高のパフォーマンスを得ることは可能ですか?

はい、少し手間がかかります。 一般的なシナリオは、RAID なしで多数のディスクを展開し、各ディスクに 1 つずつ固定された個別のキャッシュを展開することです。 追加の構成とトラフィックの分割が必要になります。 設定に関してサポートが必要な場合は、コミュニティに連絡して具体的なリクエストに対応していただくか、NGINX Plus を使用している場合はサポート チームに連絡していただければ喜んでお手伝いいたします。

50:50 ヘッダーの変更

NGINX はVaryヘッダーをキャッシュのヒットとミスに考慮しますか?

いいえ、NGINX はVaryヘッダーを自動的に処理しません。 それが問題になる場合は、プロキシ キャッシュ キーにVaryヘッダーを追加して、応答を保存するために使用される一意のキーにVaryヘッダーの値が含まれるようにするのが簡単です。 そうすれば、複数の異なるバージョンを保存できます。

51:25 キャッシュプリミティブ

すべてのキャッシュ プリミティブとディレクティブが尊重されていますか?

一般的にはそうです。 Varyヘッダーなど、考慮されないエッジ ケースがいくつかあります。 多くの場合、さまざまなキャッシュが RFC の要件を解釈する方法には、ある程度の自由度があります。可能な限り、信頼性が高く、一貫性があり、構成が簡単な実装を採用しています。

51:52 アップストリームヘッダーとデータ

アップストリーム ヘッダーとデータの両方がキャッシュされていますか?

はい、そうです。 キャッシュから応答を受信すると、応答本文だけでなくヘッダーもキャッシュされます。

52:13 *‑エンコードヘッダー

ヘッダー値とレスポンス本文はキャッシュされるので、 Transfer-Encodingのさまざまな組み合わせで NGINX が正しく動作しなかったら、かなり驚きます。 Accept-Encodingは多くの場合、 Varyヘッダーを通じて実装されるため、キャッシュ キーにVaryヘッダーを配置する必要があるという前述のコメントがそこに適用されます (これをサポートしていないクライアントの場合)。

52:56 スピーディー

SPDY ではキャッシュは機能しますか?

絶対に。 実際には NGINX カーネルに非常に深く絡み合っていますが、これは NGINX のフロントエンド プロキシと考えることができます。 はい、SPDY はキャッシュに機能します。

53:15ヴァリーヘッダー、第2ラウンド

Varyヘッダーに関する別の質問があります。 確認するには、 Varyヘッダー応答と gzip を使用している場合は、 Tracまたはコミュニティ サイトでのディスカッションを参照して、その解決策を探してください。 最も一般的なアプローチは、キャッシュ キーにVaryヘッダーを埋め込むことです。

53:45 ページスピード

質問: PageSpeed は NGINX キャッシュを使用しますか、それとも独自のキャッシュ メカニズムを使用しますか?

これはPageSpeed 開発者と共有する必要がある質問です。

54:00 その他のキャッシュ

質問: 他のコンテンツ キャッシュは NGINX と比べてどうですか?

CDN は非常に効果的なコンテンツ キャッシュ ソリューションです。 CDN はサービスとして導入されます。コンテンツがキャッシュされる方法や、その中でコンテンツが期限切れになる方法を制御することは限られていますが、コンテンツをエンドユーザーに近づけるための非常に効果的なツールです。 NGINX は Web アプリケーションを高速化するための非常に効果的なツールであり、通常は両方が一緒に導入されます。 Varnish などのスタンドアロン キャッシュの場合、これもまた、多くの点で NGINX と同様に動作する非常に優れたテクノロジです。 NGINX の利点の 1 つは、オリジン サービング アプリケーション ゲートウェイ、キャッシュ、負荷分散を 1 つのソリューションに統合していることです。 これにより、よりシンプルで統合されたインフラストラクチャが実現し、展開や管理が容易になり、問題が発生した場合のデバッグや診断も容易になります。

この投稿の元となったウェビナーを視聴するには、ここからアクセスしてください。

NGINX Plus をお試しいただくには、今すぐ30 日間の無料トライアルを開始するか、弊社にお問い合わせの上、使用事例についてご相談ください


「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"