このセクションでは、nginx では http リクエストについて説明します。nginx の特定のデータ構造は ngx_http_request_t です。 ngx_http_request_t は http リクエストのカプセル化です。 http リクエストには、リクエスト行、リクエスト ヘッダー、リクエスト本文、応答行、応答ヘッダー、および応答本文が含まれることがわかっています。
httpリクエストは代表的なリクエスト・レスポンス型のネットワークプロトコルであり、httpはファイルプロトコルであるため、リクエストラインとリクエストヘッダを解析してレスポンス行とレスポンスヘッダを出力し、1行ずつ処理することが多いです。 http サーバーを自分で作成する場合、通常は接続が確立された後、クライアントがリクエストを送信します。次に、データ行を読み取り、リクエスト行に含まれるメソッド、URI、および http_version 情報を分析します。次に、リクエストヘッダを 1 行ずつ処理し、リクエストメソッドとリクエストヘッダ情報に基づいてリクエストボディの有無とリクエストボディの長さを判断し、リクエストボディを読み込みます。リクエストを取得した後、リクエストを処理して出力する必要のあるデータを生成し、応答行、応答ヘッダー、および応答本文を生成します。応答がクライアントに送信された後、完全な要求が処理されます。もちろん、これは最も単純な Web サーバーの処理方法です。実際、nginx もこれを行いますが、たとえば、リクエスト ヘッダーが読み取られるとリクエストの処理が開始されます。 nginx は ngx_http_request_t を使用して、リクエストの解析と出力レスポンスに関連するデータを保存します。
次に、nginx が完全なリクエストをどのように処理するかについて簡単に説明します。 nginx の場合、リクエストは ngx_http_init_request から始まります。この関数では、読み取りイベントが ngx_http_process_request_line に設定されます。つまり、次のネットワーク イベントは ngx_http_process_request_line によって実行されます。 ngx_http_process_request_line の関数名から、これがリクエスト ラインを処理するものであることがわかります。前述したように、リクエストを処理するときに最初に行うことはリクエスト ラインの処理です。 ngx_http_read_request_header を通じてリクエスト データを読み取ります。次に、ngx_http_parse_request_line 関数が呼び出され、リクエスト行が解析されます。効率を向上させるために、nginx はメソッドを比較するときにステート マシンを使用してリクエスト ラインを解析し、文字列比較を直接使用せず、4 つの文字を整数に変換してから 1 回比較して、CPU 命令の数を減らします。 . これは以前にも言われました。多くの人は、リクエスト行にリクエストされたメソッド、URI、バージョンが含まれていることは知っているかもしれませんが、リクエスト行にホストも含めることができることは知りません。たとえば、GET http://www.taabao.com/uri HTTP/1.0 のようなリクエストも正当であり、ホストは www.taabao.com です。このとき、nginx はリクエスト ヘッダーのホスト フィールドを無視します。 use これをリクエスト行で使用して、仮想ホストを検索します。また、http0.9 バージョンではリクエストヘッダーがサポートされていないため、ここでは特別な処理が必要です。したがって、後でリクエスト ヘッダーを解析するとき、プロトコル バージョンは 1.0 または 1.1 になります。リクエスト行全体から解析されたパラメータは、ngx_http_request_t 構造に保存されます。
リクエスト行を解析した後、nginx は読み取りイベントのハンドラーを ngx_http_process_request_headers に設定し、後続のリクエストは ngx_http_process_request_headers で読み取られて解析されます。 ngx_http_process_request_headers 関数は、リクエスト ヘッダーを読み取るために使用されます。リクエスト ヘッダーを読み取るために ngx_http_read_request_header を呼び出し、リクエスト ヘッダーの行を解析するために ngx_http_parse_header_line を呼び出します。解析されたリクエスト ヘッダーは ngx_http_request_t のフィールド headers_in に保存されます。 headers_in はリンクされたリスト構造であり、すべてのリクエスト ヘッダーを保存します。 HTTP の一部のリクエストは特別な処理を必要とします。これらのリクエスト ヘッダーとリクエスト処理関数は、初期化中に、ハッシュ テーブルが生成されます。このハッシュで検索されます。テーブルを検索し、見つかった場合は、対応する処理関数を呼び出してリクエスト ヘッダーを処理します。例: Host ヘッダーの処理関数は ngx_http_process_host です。
nginx が 2 つのキャリッジ リターンとライン フィードを解析すると、リクエスト ヘッダーの終わりを示します。このとき、リクエストを処理するために ngx_http_process_request が呼び出されます。 ngx_http_process_request は、現在の接続の読み取りおよび書き込みイベント処理関数を ngx_http_request_handler に設定し、ngx_http_handler を呼び出して実際に完全な http リクエストの処理を開始します。ここで奇妙に思えるかもしれませんが、読み取りイベント処理関数と書き込みイベント処理関数は両方とも ngx_http_request_handler です。実際、この関数では、現在のイベントが読み取りイベントか書き込みイベントかに応じて、それぞれ ngx_http_request_t の read_event_handler または write_event_handler が呼び出されます。前述したように、この時点でリクエスト ヘッダーが読み取られているため、nginx は最初にリクエスト本文を読み取らないため、ここでは read_event_handler を ngx_http_block_reading に設定します。つまり、データは読み取られません。先ほど述べたように、データ処理の実際の開始は ngx_http_handler 関数であり、この関数は write_event_handler を ngx_http_core_run_phases に設定し、ngx_http_core_run_phases 関数を実行します。 ngx_http_core_run_phases 関数は、nginx が http リクエストの処理を複数のステージに分割して実行し、これらのステージを実行してデータを生成します。 ngx_http_core_run_phases は最終的にデータを生成するため、書き込みイベント処理関数が ngx_http_core_run_phases に設定されている理由は簡単に理解できます。ここでは、関数の呼び出しロジックについて簡単に説明します。リクエストを処理するために ngx_http_core_run_phases が最終的に呼び出されることを理解する必要があります。この部分については、リクエスト処理プロセスで説明します。 。 nginx のさまざまな段階でリクエストが処理され、最後にフィルターを呼び出してデータをフィルタリングし、切り捨てられた送信や gzip 圧縮などのデータを処理します。ここのフィルターにはヘッダーが含まれます フィルターと本文フィルター。つまり、応答ヘッダーまたは応答本文を処理します。フィルターはリンクされたリスト構造で、それぞれヘッダー フィルターと本体フィルターがあり、最初にヘッダー フィルター内のすべてのフィルターが実行され、次に本体フィルター内のすべてのフィルターが実行されます。ヘッダー フィルターの最後のフィルター、つまり ngx_http_header_filter は、すべての応答ヘッダーをスキャンし、出力する必要がある最後の応答ヘッダーは連続メモリ内にあり、出力のために ngx_http_write_filter を呼び出します。 ngx_http_write_filter は本体です フィルターの最後のもの、つまり nginx の最初の本体情報は、一連の本体フィルターの後、最終的に ngx_http_write_filter を呼び出して出力します (説明する図があります)。
ここで注意すべき点は、ユーザーのリクエストヘッダーが大きすぎてバッファーに収まらない場合、nginx はリクエストヘッダー全体をバッファーに入れるということです。このバッファーのサイズは設定項目 client_header_buffer_size によって設定されます。この大きなバッファは、large_client_header_buffers を通じて設定できます。たとえば、4 8k を構成すると、4 つの 8k バッファが使用可能になります。リクエスト ラインまたはヘッダーの整合性を維持するには、完全なリクエスト ラインまたはヘッダーを連続メモリに配置する必要があるため、完全なリクエスト ラインまたはヘッダーは 1 つのバッファーにのみ保存されることに注意してください。このように、リクエスト行がバッファ サイズより大きい場合は 414 エラーが返され、リクエスト ヘッダー サイズがバッファ サイズより大きい場合は 400 エラーが返されます。これらのパラメーターの値と nginx の実際の実践を理解した後、アプリケーション シナリオでは、プログラムを最適化するために実際のニーズに応じてこれらのパラメーターを調整する必要があります。
処理フローチャート:
上記はnginxにおけるhttpリクエストのライフサイクルです。リクエストに関連するいくつかの概念を見てみましょう。
上記は、関連する内容も含めて nginx のリクエストを紹介しています。PHP チュートリアルに興味のある友人に役立つことを願っています。