今日はリクエストについて話します。Nginx では http リクエストを指します。Nginx の具体的なデータ構造は ngx_http_request_t です。 ngx_http_request_t は http リクエストのカプセル化です。 http リクエストには、リクエスト行、リクエスト ヘッダー、リクエスト本文、応答行、応答ヘッダー、および応答本文が含まれることがわかっています。
http リクエストは典型的なリクエスト/レスポンス型のネットワーク プロトコルであり、http はテキスト プロトコルであるため、リクエスト行とリクエスト ヘッダーを分析し、応答行と応答ヘッダーを 1 行ずつ出力します。と。 (推奨される学習: nginx の使用)
http サーバーを自分で作成する場合、通常は接続が確立された後、クライアントがリクエストを送信します。次に、データ行を読み取り、リクエスト行に含まれるメソッド、URI、および http_version 情報を分析します。
その後、リクエストヘッダを一行ずつ処理し、リクエストメソッドとリクエストヘッダ情報からリクエストボディの有無とリクエストボディの長さを判断し、リクエストボディを読み込みます。
リクエストを取得した後、リクエストを処理して出力する必要のあるデータを生成し、応答行、応答ヘッダー、応答本文を生成します。
応答をクライアントに送信した後、完全なリクエストが処理されます。もちろん、これは最も単純な 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 の一部のリクエストには特別な処理が必要です。これらのリクエスト ヘッダーとリクエスト処理関数は、マッピング テーブル、つまり ngx_http_headers_in に保存されます。初期化中にハッシュ テーブルが生成されます。リクエストが解析されるとき、リクエスト後、ヘッダーを含む場合は、まずハッシュ テーブルを検索し、見つかった場合は、対応する処理関数を呼び出してリクエスト ヘッダーを処理します。例: 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 が呼び出されることを理解する必要があります。生成されたレスポンス ヘッダーは、ngx_http_request_t の headers_out に配置されます。この部分を記述します。リクエスト処理プロセスで説明しましょう。 Nginx のさまざまな段階でリクエストが処理され、最後にフィルターを呼び出してデータをフィルタリングし、切り捨てられた送信や gzip 圧縮などのデータを処理します。
ここでのフィルターには、応答ヘッダーまたは応答本文を処理するヘッダー フィルターと本文フィルターが含まれます。フィルターはヘッダーフィルターとボディフィルターのリンクリスト構造になっており、ヘッダーフィルター内のすべてのフィルターが最初に実行され、次にボディーフィルター内のすべてのフィルターが実行されます。
ヘッダー フィルターの最後のフィルターは ngx_http_header_filter です。このフィルターはすべての応答ヘッダーをスキャンします。出力する必要がある最後の応答ヘッダーは連続メモリ内にあり、出力のために ngx_http_write_filter を呼び出します。
ngx_http_write_filter は本文フィルターの最後のものであるため、Nginx の最初の本文情報は、一連の本文フィルターを通過した後、最終的に ngx_http_write_filter を呼び出して出力します (説明する図があります)。
ここで注意すべき点は、Nginx はリクエスト ヘッダー全体をバッファーに入れるということです。このバッファーのサイズは、構成項目 client_header_buffer_size によって設定されます。ユーザーのリクエスト ヘッダーが大きすぎて、このバッファーに収まらない場合は、 , その後、Nginx はリクエスト ヘッダーを保持するために新しいより大きなバッファーを再割り当てします。この大きなバッファーは、large_client_header_buffers を通じて設定できます。48k の構成などのバッファーのlarge_buffer グループは、4 つの 8k バッファーが使用可能であることを意味します。
リクエスト ラインまたはリクエスト ヘッダーの整合性を維持するには、完全なリクエスト ラインまたはリクエスト ヘッダーを連続メモリに配置する必要があることに注意してください。したがって、完全なリクエスト ラインまたはリクエスト ヘッダーは保存されるだけです。バッファ内。
このように、リクエスト行がバッファサイズより大きい場合は414エラーが返され、リクエストヘッダのサイズがバッファサイズより大きい場合は400エラーが返されます。これらのパラメーターの値と Nginx の実際の実践を理解した後、アプリケーション シナリオでは、プログラムを最適化するために実際のニーズに応じてこれらのパラメーターを調整する必要があります。
処理フローチャート:
上記は、Nginx における http リクエストのライフ サイクルです。
以上がnginx リクエストを処理するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。