nginx httpモジュールのデータ保存構造の概要

nginx httpモジュールのデータ保存構造の概要

このセクションから、http モジュールの実装原理について説明します。http モジュールで非常に重要な点は、http ブロック、server ブロック、location ブロックにデータを格納する方法です。nginx の一部の設定項目は、複数の設定ブロックで使用できます。http ブロック、server ブロック、location ブロックの 2 つ以上の設定ブロックが設定項目で構成されているとき、nginx がこれらの設定項目をどのように処理するかという疑問が生じます。この記事では主に、http ブロック内の各モジュールのデータがどのように保存されるかについて説明します。これは、nginx の http モジュールがどのように動作するかを理解するための重要な基礎となります。

1. コアモジュールの保管方法

nginx の実行中は、属性conf_ctxを持つグローバル設定構造ngx_cycle_tがあります。この属性は、すべての nginx モジュールの設定を格納する配列です。この配列の長さは、nginx モジュールの数と同じです。ただし、 conf_ctx配列の最初の次元にはコア モジュールの構成のみが格納され、他のモジュールの対応する位置にある配列要素は実際には NULL であることに注意してください。 conf_ctxでは、各コアモジュール設定構造の保存場所は、すべてのモジュール(コア以外のモジュールを含む)内のモジュールの相対的な位置と一致しています。次の図は、nginx ストレージコアモジュールの構造図です。

ここでマークされているeventshttp 、デモンストレーションの便宜上のみ追加されています。本質的に、この配列の要素の型はvoid*ポインタです。ポインタが指す特定の構造体の型については、各コアモジュール自体の定義に基づいています。

http モジュールの下では、 ngx_http_conf_ctx_t型の構造体を指し、これは http 構成ブロック内の各構成項目のデータを格納するために使用されます。この構造の定義は次のとおりです。

typedef構造体{
 	//MAIN レベルの構成を保存します void **main_conf;
 	//SRV レベルの構成を保存します void **srv_conf;
 	//LOC レベルの構成を保存します void **loc_conf;
} ngx_http_conf_ctx_t;

nginx.conf 構成ファイルでは、http ブロックの下に server ブロックがあり、server ブロックの下に location ブロックがあることがわかります。さらに、location ブロックの下にサブ location ブロックがある場合もあります。ここでのngx_http_conf_ctx_t構造体の役割は、これらすべての構成に対応する構造データを格納することです。まず、nginx.conf 設定ファイルでは、設定項目はモジュールによって定義されることを明確にする必要があります。モジュールは複数の設定項目を定義でき、これらの設定項目の解析は、このモジュールによって定義されたメソッドによって実行されます。ただし、一般的には、モジュールは 1 つの構造体のみを定義し、この構造体内のさまざまな属性は、モジュールによって定義された各構成項目のデータに対応します。つまり、各モジュールによって定義されたメソッドを通じて、モジュールによって定義された構成項目に対応する構成を、モジュールによって定義された構造体に変換します。ここで説明する構造は、上記のmain_confsrv_conf 、およびloc_confの設定に対応しています。上記の定義から、これら 3 つの属性の型はポインタ型の配列であり、配列の長さはモジュールの数、より正確には http モジュールの数に対応していることがわかります。各 http モジュールの設定を解析する前に、nginx は現在のモジュールの種類 (http モジュール) における各 http モジュールの相対的な位置をマークします。各 http モジュールの相対的な位置は、上記の 3 つの属性の配列の添え字に対応します。前述のように、各 http モジュールには、モジュールによって定義されたすべての構成データを格納するための構成構造が 1 つだけあり、これらの構成構造は上記の 3 つの配列に格納されます。このように、実際には上記の構造の 3 つの属性、各属性配列は http モジュールの構成構造に対応していることがわかります。

ここでの各モジュールには、配列の対応するインデックス位置に格納される構造があるため、なぜここで 3 つの配列が必要になるのでしょうか。たとえば、 ngx_http_core_moduleの場合、 http モジュール内の相対的な位置は最初です。つまり、 main_conf[0]srv_conf[0] 、およびloc_conf[0]はすべてngx_http_core_moduleの構成構造を格納します。なぜ 3 つの構造が必要なのでしょうか?ここで説明する必要があるのは、各 http モジュールについて、使用範囲に応じて構成項目を 3 つのカテゴリに分割することです。http ブロックのみ、http ブロックとサーバー ブロックで使用可能、http ブロック、サーバー ブロック、およびロケーション ブロックで使用可能です。設定項目の種類ごとに異なる構造が使用されます。たとえば、 ngx_http_core_module 、http ブロックのみに使用される設定項目を格納するngx_http_core_main_conf_t ngx_http_core_srv_conf_t定義し、http ブロックとサーバー ブロックに使用される設定項目を格納する ngx_http_core_srv_conf_t を定義し、http ブロック、サーバー ブロック、およびロケーション ブロックに使用される設定項目を格納するngx_http_core_loc_conf_t定義します。上記の配列に対応して、 main_conf[0]の構造型はngx_http_core_main_conf_tsrv_conf[0]の構造型はngx_http_core_srv_conf_tloc_conf[0]の構造型はngx_http_core_loc_conf_tです。この時点で、問題を明確にする必要があります。たとえば、特定の設定項目は http ブロックで設定されますが、そのタイプは http ブロック、サーバーブロック、およびロケーションブロックで使用できるため、 loc_conf[0]に格納されます。つまり、現在の観点からすると、上記の構造全体には、 http ブロックで解析された各設定項目のデータが格納されます。では、nginx は構成項目がこれら 3 つのタイプのどれであるかをどのようにマークするのでしょうか?これは主にngx_command_t構造によって定義されます。次の 3 つの典型的な構成があります。

{
 ngx_string("variables_hash_max_size"),
 NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1、
 ngx_conf_set_num_slot、
 	NGX_HTTP_MAIN_CONF_OFFSET、
 	オフセット(ngx_http_core_main_conf_t、variables_hash_max_size)、
 	NULL
},
{
 ngx_string("聞く"),
 	NGX_HTTP_SRV_CONF | NGX_CONF_1MORE、
 	ngx_http_core_listen、
 	NGX_HTTP_SRV_CONF_OFFSET、
 	0,
 	NULL
},
{
 ngx_string("ルート"),
 	NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LIF_CONF
 	 | NGX_CONF_TAKE1、
 	ngx_http_core_root、
 	NGX_HTTP_LOC_CONF_OFFSET、
 	0,
 	NULL
},

ここでは、 variables_hash_max_sizelistenroot例に挙げます。これら 3 つの命令は、 ngx_http_core_moduleモジュールによって定義された設定項目ですが、保存場所はまったく異なります。注意する必要があるのは、各ディレクティブの 4 番目の属性の定義です: NGX_HTTP_MAIN_CONF_OFFSETNGX_HTTP_SRV_CONF_OFFSET 、およびNGX_HTTP_LOC_CONF_OFFSET 。これら 3 つのタイプの定義には 2 つの意味があります。1 つは、この設定項目が http ブロックのみに使用されるか、http ブロックとサーバー ブロックの両方に使用できるか、http ブロック、サーバー ブロック、およびロケーション ブロックの両方に使用できるかを示すことです。もう 1 つの意味は、前述のngx_http_conf_ctx_tでのこの設定項目のオフセットを定義することです。いわゆるオフセットとは、 ngx_http_conf_ctx_t構造オブジェクトのポインタ アドレスがわかっている場合、現在の設定項目に格納されている配列をここでのオフセットを通じて計算できることを意味します。ここで、 ngx_conf_parse()メソッドのコードの一部を示します。このメソッドは主に nginx.conf 設定ファイルを解析するために使用されます。設定項目を解析すると、すべてのモジュールで設定項目の定義が見つかります。設定項目が見つかった場合は、設定項目に対応する構造を取得しようとし、設定項目で指定されたメソッドを呼び出して設定項目データを解析します。ここで設定項目に対応する構造体を取得しようとする場合、上記のオフセットを使用する必要があります。この構成項目を取得する方法は次のとおりです。

// 設定オブジェクトを検索します。 NGX_DIRECT_CONF 定数は、設定ストレージ領域のアドレス指定方法を指定するためにのみ使用されます。これはコアモジュールでのみ使用されます if (cmd->type & NGX_DIRECT_CONF) {
 conf = ((void **) cf->ctx)[cf->cycle->modules[i]->index];

 // NGX_MAIN_CONF 定数には 2 つの意味があります。1 つは、指定された命令のコンテキストが main であるということです (実際には、コア モジュールを参照しています)。
 // 2 番目は、構成保存領域のアドレス指定方法を指定します。
} そうでない場合 (cmd->type & NGX_MAIN_CONF) {
 conf = &(((void **) cf->ctx)[cf->cycle->modules[i]->index]);

 // コア モジュールを除き、他のタイプのモジュールは 3 番目の構成アドレス指定方法を使用します。つまり、cmd->conf の値に応じて、cf->ctx から対応する構成を取得します。 httpモジュールを例にとると、cf->confのオプション値はNGX_HTTP_MAIN_CONF_OFFSET、
 // NGX_HTTP_SRV_CONF_OFFSET、NGX_HTTP_LOC_CONF_OFFSET、
 // それぞれ 3 つの http 構成レベル「http{}」、「server{}」、「location{}」に対応します。

 // この if 判断の主な機能は、cf->ctx の型が ngx_http_conf_ctx_t であり、cmd->conf の主な値がオプションであるかどうかです // NGX_HTTP_MAIN_CONF_OFFSET、NGX_HTTP_SRV_CONF_OFFSET、NGX_HTTP_LOC_CONF_OFFSET、
 // ngx_http_conf_ctx_t の属性は main_conf、srv_conf、loc_conf であることがわかります。
 // 実際、ここでは現在の構成オブジェクトが 3 つの配列のどれに格納されているかを計算します。default_type 命令を例に挙げます。
 // ngx_command_t の設定は次のとおりです。
 // {ngx_string("default_type"),
 // NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1、
 // ngx_conf_set_str_slot、
 // NGX_HTTP_LOC_CONF_OFFSET、
 // offsetof(ngx_http_core_loc_conf_t、default_type)、
 // NULL},
 // ご覧のとおり、conf 属性の値は NGX_HTTP_LOC_CONF_OFFSET であり、loc_conf 配列に格納されていることを意味します。
 // 配列の要素型はngx_http_core_loc_conf_tなので、次のngx_command_tが
 // オフセット属性の値は offsetof(ngx_http_core_loc_conf_t, default_type) として指定されます。
 // これは、ngx_http_core_loc_conf_t 構造で default_type 属性が計算される方法です。
 // 次のif判断ステップconfp = *(void **) ((char *) cf->ctx + cmd->conf);により、現在使用されている構造体がmain_conf、srv_confにあるかどうかを計算できます。
 // そしてその配列内のloc_conf、そして2番目のステップを通してconf = confp[cf->cycle->modules[i]->ctx_index];
 // 計算により、配列内の構造体の特定の位置を計算し、構造体データを取得できます。
 // この計算方法は、http モジュールの設定項目の取得にのみ適用可能であることに注意してください。http モジュールの設定構造のみが // ngx_http_conf_ctx_t 型であるためです。} else if (cf->ctx) {
 confp = *(void **) ((char *) cf->ctx + cmd->conf);

 if (confp) {
  conf = confp[cf->cycle->modules[i]->ctx_index];
 }
}

ここでは、最後のelse ifブランチに注目する必要があります。これは、http モジュールが構成項目の定義に基づいて、構成項目に対応する構造の保存場所を計算する方法を示しています。次の図は、http ブロック構成を含む全体的な構造を示しています。

2. サーバーブロックの保管

上で述べたように、 ngx_http_conf_ctx_t構造を使用して http ブロック内のすべての構成項目を保存できますが、サーバー ブロック内の構成項目はどのように保存されるのでしょうか。これは主にngx_http_core_moduleモジュールのmain_conf 、つまり上記のmain_conf[0]に対応するngx_http_core_main_conf_t構造体に格納されます。この構造体にはservers属性があり、この属性の型はngx_array_t 、つまり配列です。つまり、各 http 構成ブロックの下では、各 server 構成ブロックがservers配列の要素に対応し、配列の要素タイプは http ブロックの要素タイプと一致しており、依然としてngx_http_conf_ctx_tです。ただし、違いは、現在の構成項目が http ブロックだけでなく、 server ブロックまたは location ブロックで使用可能である必要があるため、構成項目のタイプは上記のNGX_HTTP_SRV_CONF_OFFSETNGX_HTTP_LOC_CONF_OFFSETのいずれかである必要があり、 NGX_HTTP_MAIN_CONF_OFFSETにすることはできないことです。したがって、各サーバー構成ブロックに対応する構成構造は引き続きngx_http_conf_ctx_tですが、そのmain_conf配列には対応する構成項目がなく、 http ブロックからの構成項目のみを継承できます。継承なので、nginx は http ブロックに対応するngx_http_conf_ctx_tmain_conf配列に配列のポインタを直接指すことで処理します。以下は、2 つのサーバー ブロックの構成図です。

この図は少し複雑に見えますが、複雑ではありません。構成ブロックの区分に従って、上のngx_http_conf_ctx_t http ブロックの構成を格納し、下の 2 つのngx_http_conf_ctx_tは 2 つの server ブロックの構成を格納します。中間参照処理は、http ブロックのngx_http_core_moduleモジュールに対応するngx_http_core_main_conf_t.serversを通じて行われます。注目すべき点は、上記のサーバー ブロック構成では、 main_confポインターが http ブロック内の対応するngx_http_conf_ctx_tmain_conf属性を指していることです。

3. ロケーションブロックの保存方法

ロケーション ブロックの保存の場合、その保存構造は依然としてngx_http_conf_ctx_tであり、現在の構成項目はロケーション ブロック内にあるため、そのタイプは間違いなくNGX_HTTP_MAIN_CONF_OFFSETおよびNGX_HTTP_SRV_CONF_OFFSETにはなりません。つまり、ロケーション構成項目を解析して取得したデータは、 loc_conf配列に保存される必要があります。したがって、サーバー ブロックと同様に、ロケーション ブロックに対応するngx_http_conf_ctx_t構造体のmain_confsrv_conf 、現在の場所が配置されている http ブロックのmain_confと、それが配置されているサーバー ブロックのsrv_conf配列を指します。

さらに、サーバー ブロックの下には複数のロケーション ブロックがあります。ストレージ構造の観点から見ると、これらのロケーション ブロックはキューの形式で編成されています。サーバー ブロックと同様に、このキューは、配置されているサーバー ブロックに対応するngx_http_conf_ctx_tloc_conf[0]に格納されます。ここでのloc_conf[0]の構造型はngx_http_core_loc_conf_sであり、これには場所キューであるタイプngx_queue_tの属性locationsがあります。最後に、ここでのlocations属性は、server ブロックの下の複数の location ブロックを表すだけではなく、location 構成ブロックの下に複数の location ブロックを引き続き構成できるため、再帰的に複数の location ブロックを表すことに注意してください。これらのサブロケーション ブロックのタイプは実際にはngx_http_core_loc_conf_sなので、 locations属性によって表すこともできます。以下は、場所構成ブロックを追加する構造の概​​略図です。

この図は、2 つのロケーションが並列に編成されている状況を示しています。main_conf とsrv_confは、それぞれ現在のロケーション ブロックが配置されている http ブロックのmain_confと server ブロックのsrv_conf main_conf指しており、2 つのロケーション ブロックに対応する構造は、キュー方式でngx_http_core_loc_conf_tに編成されています。

4. まとめ

この記事では、まずngx_cycle_t構造から始め、 http ブロックの設定項目がngx_cycle_tにどのように格納されるかを紹介します。また、 http ブロック、 server ブロック、 location ブロックの格納方法と、それらの相互構成についても紹介します。

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

以下もご興味があるかもしれません:
  • nginx HTTPモジュール設定の一般的な手順

<<:  H5 WeChatパブリックアカウント認証を実装するための簡単な手順

>>:  MySQL トリガーの定義と使用方法の簡単な例

推薦する

JavaScript でカルーセル効果を実装する

この記事では、カルーセルの効果を実現するためのJavaScriptの具体的なコードを参考までに共有し...

Alpine Dockerイメージフォント問題解決操作

1. フォントを実行し、フォント フォルダーを開いて、使用するフォント ファイルを見つけます。 2....

jQueryはテーブル行データのスクロール効果を実現します

この記事の例では、テーブル行データのスクロール効果を実現するためのjQueryの具体的なコードを参考...

Docker は MySQL をインストールし、中国語の文字化けの問題を解決します

目次1. MySQLイメージを取得する2. ダウンロードが完了したか確認する3. MySQLはローカ...

JavaScript の静的スコープと動的スコープを例を使って説明します

目次序文静的スコープと動的スコープ静的スコープ実行プロセス動的スコープ実行プロセスエクササイズ練習1...

MySQL の重要なパフォーマンス インデックスの計算と最適化方法の概要

1 QPS 計算 (1 秒あたりのクエリ数) MyISAMエンジンベースのDBの場合 MySQL&g...

Linuxネットワーク設定の基本操作コマンドを詳しく解説

目次ネットワーク構成を表示するネットワークインターフェース情報を表示する---ifconfigルーテ...

CSSレイアウトで中央揃えレイアウトを実現する方法

1. 親コンテナーをテーブルに設定し、子をインライン要素に設定します。テキストを表示するサブコンテン...

EXPLAIN を使って MySQL の SQL 実行プランを分析する方法

序文MySQL では、EXPLAIN コマンドを使用して、テーブルの接続方法や SELECT ステー...

Vue大画面表示適応方法

この記事では、vueの大画面表示適応の具体的なコードを参考までに紹介します。具体的な内容は以下のとお...

Vue再帰コンポーネントの簡単な使用例

序文多くの学生は既に再帰に精通していると思います。アルゴリズムの問​​題を解決するために再帰がよく使...

CSSは、入力ボックスのフローティングテキスト効果を実現するために、placeholder-shown疑似クラスを使用します。

この記事では、:placeholder-shown 疑似クラスを使用して、純粋な CSS で浮動疑問...

Docker、プレーヤー機能を備えたCMSオンデマンドシステムを構築

目次文章1. 機械を準備する2. Dockerをインストールする1. 依存パッケージをインストールす...

モバイル端末におけるビューポートの具体的な使用法についての簡単な説明

目次1. 基本概念1.1 2種類のピクセル1.2 3つのビューポート2. ビューポート設定3. 1回...

検証コード干渉を実装する js (静的)

この記事では、検証コード干渉を実装するためのjsの具体的なコードを参考までに共有します。具体的な内容...