ホームページ  >  記事  >  バックエンド開発  >  nginx キャッシュ システムの設計原則

nginx キャッシュ システムの設計原則

WBOY
WBOYオリジナル
2016-08-08 09:20:08877ブラウズ

ここでは、nginx のキャッシュ システムを手がかりとして、キャッシュ サーバーの設計と関連する詳細について説明します。紙面の都合上、詳しくは説明しません。関連する詳細については、ぜひ議論に参加してください。

キャッシュ サーバーがバックエンドからファイルを取得した後、ファイルはクライアントに直接送信されるか (科学的名前は透過送信)、後続の同一のリクエストがキャッシュ サーバーにアクセスするときにローカル コピーを直接使用できます。はい、使用できれば可能です。ローカルにキャッシュされたファイルが後続のリクエストによってアクセスされる場合、それはキャッシュ内でのヒットと呼ばれます。ファイルのキャッシュ コピーがローカルにない場合、キャッシュ サーバーはバックエンドに移動して、設定に従ってファイルを取得するか、ドメイン名を解決する必要があります。これはキャッシュ ミス、つまりミスと呼ばれます。キャッシュ サーバーの詳細については、nginx キャッシュ システムを分析するときに詳しく説明します。

nginx のストレージ システムは 2 つのカテゴリに分かれており、1 つは proxy_store を通じて開かれ、URL 内のファイル パスに従ってローカルに保存されます。たとえば、/file/2013/0001/en/test.html とすると、nginx は指定された保存ディレクトリに各ディレクトリとファイルを順番に作成します。もう 1 つのタイプは、proxy_cache を通じて開かれます。この方法で保存されたファイルは、URL パスに従って編成されませんが、いくつかの特別なメソッド (ここではカスタム メソッドと呼ばれます) を使用して管理されます。カスタム メソッドに焦点を当てて分析します。では、これら 2 つの方法にはそれぞれどのような利点があるのでしょうか?

URL パスによってファイルを保存する方法は、プログラムの処理が比較的簡単ですが、パフォーマンスは良くありません。まず、一部の URL は非常に長く、ローカル ファイル システム上にこのような深いディレクトリを作成する必要がある場合、ファイルを開いたり検索したりするのに非常に時間がかかります (カーネルでパス名を使用して i ノードを検索するプロセスを思い出してください)。カスタム方法を使用してパターンを処理する場合、パターンはファイルやパスから分離できませんが、複雑さが増したり、URL の長さが原因でパフォーマンスが低下したりすることはありません。ある意味、これはユーザーモードのファイルシステムであり、最も典型的なものは Squid の CFS です。 nginx の使用方法は比較的単純で、主に管理用の URL の md5 値に依存しますが、これについては後で分析します。

キャッシュは、バックエンドからコンテンツを取得してクライアントに送信することから切り離せません。受信と送信を同時に行う必要がある具体的な処理方法は、誰でも簡単に思いつきます。他の方法 (読み取り後に送信するなど) は非効率すぎます。ここで、nginx は受信と送信を同時に行うことに注意してください。使用される構造は ngx_event_pipe_t であり、これがバックエンドとクライアント間の通信の媒体です。構造体は一般的なコンポーネントであるため、ストレージに関係する関連機能を処理するにはいくつかの特別なタグが必要となるため、キャッシュ可能なメンバーがこの重要なタスクを引き受けます。

p->cacheable = u->cacheable || u->store;

つまり、cacheable が 1 の場合は保存する必要があり、それ以外の場合は保存されません。それでは、u->cacheable と u->store は何を表しているのでしょうか?これらはそれぞれ、前述の 2 つのメソッド、つまり proxy_cache と proxy_store を表します。

(知識を追加すると、nginx がバックエンド データを取得するとき、その動作は proxy_buffering によって制御され、バックエンド サーバーの応答バッファリングが有効になります。バッファリングが有効な場合、nginx はプロキシ サーバーが応答を非常に迅速に配信できると想定します。応答はバッファに入れられ、proxy_buffer_size と proxy_buffers を使用して設定できます。バッファリングが無効な場合、応答はハードディスクに書き込まれます。すぐにクライアントに配信されます)


これらはすべて、nginx キャッシュ機能のコアにはまだ触れていません。実装の観点から見ると、nginx の上流構造にはキャッシュと呼ばれるメンバーがあり、そのタイプは ngx_shm_zone_t です。キャッシュ機能を有効にすると、キャッシュ メンバーは共有メモリの管理に使用されます (なぜ共有メモリが使用されるのでしょうか?)。他の方法で格納される場合、メンバーは NULL になります。もう 1 つ説明する必要がある点は、キャッシュ システムでは通常、ファイルはストア オブジェクト、つまりキャッシュ オブジェクトと呼ばれるため、キャッシュする前にストア オブジェクトを作成する必要があるということです。重要な問題は、それを作成する時間をどのように選択するかです。これについてはどう思いますか。まず、ファイルをキャッシュする必要があるかどうかを確認する必要があります。明らかに、GET メソッドでリクエストされたファイルは通常、キャッシュする必要があるため、リクエスト処理の初期段階で GET メソッドが見つかったら、最初にオブジェクトを作成できます。しかし、多くの場合、GET メソッドで要求されたファイルであっても、オブジェクトを作成するのが早ければ、時間とスペースを無駄にするだけでなく、最終的には破棄されてしまいます。では、GET リクエストのストレージには何が影響するのでしょうか?これは、応答ヘッダーの Cache-control フィールドです。このフィールドは、ファイルをキャッシュできるかどうかをプロキシまたはブラウザに伝えます。一般に、キャッシュ サーバーは、応答ヘッダーに Cache-control フィールドがない場合、デフォルトで要求をキャッシュします。

この考慮事項に基づいて、私たちが開発したキャッシュ サーバーは、応答ヘッダーが解析され、キャッシュの十分な証拠が得られた後にのみキャッシュ オブジェクトを作成します。残念ながら、nginx ではこれができません。

nginx は ngx_http_upstream_init_request 関数でキャッシュ オブジェクトの作成を完了します。この関数は http 処理のどの段階にありますか?バックエンドとの接続を確立する前に。個人的にはこの場所はふさわしくないと思います。 。 。どう思いますか?

作成プロセスに関しては、ngx_http_upstream_cache 関数を読むことができます。ここでは、nginx と比較してキャッシュを分析します。このリクエストでは、store という名前のメンバーを使用して、キャッシュ オブジェクトとの接続を確立します。 nginx にも同様のことが当てはまり、リクエスト構造に同じことを行うキャッシュ メンバーがあります。違いは、ストアのメンバーに対応するスペースが共有メモリ内にあるのに対し、nginx は r->pool 内でそれを適用することです (なぜこれを行うのでしょうか?)。

次のステップでは、nginx は設定に従ってキャッシュ オブジェクトのキーを生成する必要があります。これは通常、md5 を使用して計算されます。このキーは、システム内のキャッシュ オブジェクトの一意の識別子として機能します。MD5 の衝突について心配している人も多いでしょう。特に要求が厳しくなく、処理が比較的簡単であれば、この要件は完全に受け入れられると思います。

次に対処する必要があるのは、ファイルをディスクにどのように保存するかということです。

以前に使用した例を見てみましょう: /file/2013/0001/en/test.html。実際、nginx はこれをファイル名として使用します。それでおしまい?ファイルを保存するディレクトリを見つけて、その中にそのようなファイルが大量にある場合はどうなるでしょうか?ほとんどのファイル システムでは 1 つのディレクトリ内のファイル数に制限があるため、このような単純かつ大雑把な処理は不可能であることがわかっています。何をするか? nginx では、構成を通じてマルチレベルのディレクトリを使用して、この問題を解決できます。簡単に言うと、nginx は、levels ディレクティブを使用して、ディレクトリ レベルの数 (コロンで区切られています) と各ディレクトリ名の文字数を指定します。この例では、levels=1:2 が設定されていると仮定します。 2 レベルのディレクトリが使用されます。第 1 レベルのディレクトリ名は 1 文字で、第 2 レベルのディレクトリ名は 2 文字です。ただし、nginx は最大 3 レベルのディレクトリ (levels=xxx:xxx:xxx) をサポートします。

では、ディレクトリ名を構成する文字はどこから来たのでしょうか? 保存ディレクトリが /cache、levels=1:2 であると仮定すると、上記のファイルは次のように保存されます:

/cache/0/8d/8ef9229f02c5672c747dc7a324d658d​​0

0 と 8d という 2 つのディレクトリ名がどのように由来したかがわかりますので、説明する必要はありません。

オブジェクトの作成後、ngx_http_file_cache_exists によって処理されるオブジェクト管理構造をキャッシュする必要があります。

このファイルを作成するときに現在のディレクトリとファイルがすでに存在している場合、どうすればよいですか?コードを確認して、nginx がそれをどのように処理するかを確認できます。

議論は終わりました。実際には、次回はバックエンドコンテンツの到着の処理について説明します。

詳細:

http://www.pagefault.info/?p=123

http://www.pagefault.info/?p=375

上記では、nginx のキャッシュ システムの設計原則をその側面も含めて紹介していますが、PHP チュートリアルに興味のある友人に役立つことを願っています。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:PHPの正規表現次の記事:PHPの正規表現