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 トリガーの定義と使用方法の簡単な例

推薦する

SEATAトランザクションサービスDockerのデプロイ手順の詳細説明

1. データベース認証ステートメントを作成する > データベース seata を作成します。 ...

Vue+elementUI コンポーネントは、折りたたみ可能な動的レンダリングのマルチレベル サイドバー ナビゲーションを再帰的に実装します。

かなり前に実装された機能ですが、クリックすると選択したメニュー項目の背景色が白くなることに気付きまし...

Linux の高並列性とパフォーマンス最適化の落とし穴の紹介

目次序文Linux アプリケーション実行中に開いているファイルが多すぎる問題の分析と解決Linux ...

モバイルブラウザが位置をサポートしない場合の解決策: 修正

具体的な方法は以下の通りです。 CSSコードコードをコピーコードは次のとおりです。 .wap_bot...

Vueはシンプルなタイマーコンポーネントを実装します

プロジェクトを実行すると、リアルタイム更新、広告アニメーションの連続表示などの要件に遭遇することは避...

MySQL 外部キー設定方法の例

1. 外部キーの設定方法1. MySQL では、2 つのテーブルを関連付けるために、外部キー (FO...

HTML特殊文字の徹底分析

HTML徹底解析(14)特殊文字 ■ よく使われる特殊文字 HTMLタグを知っていれば、特殊文字の使...

要素 el-button ボタンコンポーネントの使用の詳細な説明

1. 背景ボタンは非常によく使われており、Element のボタン機能は非常に包括的です。この記事で...

Vueを使用してタイマー機能を実装する

この記事の例では、タイマー機能を実装するためのVueの具体的なコードを参考までに共有しています。具体...

ウェブデザイナーが持つべき資質と能力

Web デザインは、インターネットの出現後に誕生した新興の周辺産業です。 Web ページは店頭のよう...

CentOS7でルートパスワードをリセットする方法

レンガを移動するプロセスでは、さまざまな環境および構成の問題があり、毎回異なるエラーが発生します。 ...

マウスが画像のハイパーリンク上を通過するときに画像のサイズ(幅、高さ)を変更する CSS

マウスが画像の上を通過したときに画像のハイパーリンクを変更する方法:コードをコピーコードは次のとおり...

iframeノードの初期化の問題に関する議論

今日、ふとリッチテキストエディタの制作原理を見直してみようと思いました。それで、彼は何も言わずにそれ...

Linuxシステムはルートアカウントのリモートログインコマンドを禁止しています

ps: Linux システムで root アカウントのリモート ログインを無効にする方法は次のとおり...

WeChatアプレットがフォーム検証を実装

WeChatアプレットフォームの検証、参考までに具体的な内容は次のとおりです。プラグインWxVali...