connection
Nginx では、接続は、接続されたソケットと読み取りイベントを含む tcp 接続のカプセル化です。 、イベントを書き込みます。 Nginx によってカプセル化された接続を使用すると、接続の確立、データの送受信など、接続関連の問題を Nginx で簡単に処理できます。 (推奨学習: nginx の使用)
Nginx での http リクエストの処理は接続に基づいているため、Nginx は Web サーバーとしてだけでなく、メールサーバーとしても使えます。もちろん、Nginx が提供する接続を使用して、あらゆるバックエンド サービスを処理できます。
TCP 接続のライフサイクルと組み合わせて、Nginx が接続をどのように処理するかを見てみましょう。
まず、Nginx が起動すると、構成ファイルを解析して監視する必要があるポートと IP アドレスを取得します。次に、Nginx マスター プロセスで、最初に監視ソケットを初期化します (ソケットを作成し、 addrreuse とその他のオプションを設定し、指定された IP アドレス ポートにバインドし、再度リッスンします)、複数の子プロセスをフォークアウトすると、子プロセスは新しい接続を受け入れるために競合します。
この時点で、クライアントは Nginx への接続を開始できます。
クライアントとサーバーが 3 ウェイ ハンドシェイクを通じて接続を確立すると、Nginx のサブプロセスは正常に受け入れ、確立された接続のソケットを取得して、Nginx による接続のカプセル化を作成します。 、ngx_connection_t 構造体。
次に、読み取りおよび書き込みイベント処理関数を設定し、クライアントとデータを交換するための読み取りおよび書き込みイベントを追加します。最後に、Nginx またはクライアントが積極的に接続を閉じ、この時点で接続は終了します。
もちろん、Nginx をクライアントとして使用して、他のサーバー (アップストリーム モジュールなど) にデータをリクエストすることもできます。このとき、他のサーバーと作成された接続も ngx_connection_t にカプセル化されます。
Nginx はクライアントとして、まず ngx_connection_t 構造体を取得し、次にソケットを作成し、ソケットの属性 (ノンブロッキングなど) を設定します。次に、読み取りイベントと書き込みイベントを追加し、connect/read/write を呼び出して接続を呼び出し、最後に接続を閉じて ngx_connection_t を解放します。
Nginx では、各プロセスには接続数の上限があり、システムの fd の制限とは異なります。オペレーティング システムでは、ulimit -n を使用して、プロセスがオープンできる fd の最大数 (nofile です) を取得できます。各ソケット接続は 1 つの fd を占有するため、プロセスの最大接続数も制限されます。もちろん、プログラムがサポートできる同時実行の最大数にも直接影響します。fd が使い果たされると、ソケットの作成は失敗します。
Nginx は、worker_connectons を設定することで、各プロセスでサポートされる接続の最大数を設定します。この値が nofile より大きい場合、実際の最大接続数は nofile となり、Nginx が警告します。
Nginx は実装時に接続プールを通じて管理され、ワーカー プロセスごとに独立した接続プールがあり、接続プールのサイズは worker_connections です。ここで接続プールに保存されるものは実際には実際の接続ではなく、worker_connections サイズの ngx_connection_t 構造体の配列にすぎません。
そして、Nginx はリンクされたリスト free_connections を通じてすべての無料 ngx_connection_t を保存します。接続が取得されるたびに、無料接続リストから 1 つ取得されます。使用後は、無料接続に戻されます。リスト。
ここで、多くの人が worker_connections パラメータの意味を誤解し、この値が Nginx が接続を確立できる最大値であると考えます。実際、この値は各ワーカー プロセスによって確立できる接続の最大数を表すため、Nginx によって確立できる接続の最大数は、worker_connections * worker_processes となる必要があります。
もちろん、ここで話しているのは接続の最大数です。ローカル リソースに対する HTTP リクエストの場合、サポートできる同時実行の最大数は、worker_connections * worker_processes です。HTTP の場合は、その逆です。プロキシの場合、同時実行の最大数は、worker_connections * work_processes/2 である必要があります。
リバース プロキシ サーバーとして、各同時接続はクライアントとの接続とバックエンド サービスとの接続を確立し、2 つの接続を占有することになるためです。
そうですね、クライアントが接続した後、複数のアイドルプロセスが接続をめぐって競合することは前に述べました。この競合が不公平につながることは簡単にわかります。プロセスが受け入れられれば、より多くの機会があります。事前に何らかの制御が行われていない場合、新しい TCP 接続が受け入れられたときに、アイドル状態の接続を取得できず、この接続を他のプロセスに転送できないため、最終的にはtcp 接続は処理できず、終了されます。
明らかに、これは不公平です。一部のプロセスは空き接続を持っていますが、それらを処理する機会がありません。一部のプロセスは、空き接続がないために人為的に接続を破棄します。では、この問題をどうやって解決すればよいでしょうか?
まず、Nginx の処理では、まず accept_mutex オプションをオンにする必要があります。このとき、accept_mutex を取得したプロセスのみが accept イベントを追加します。つまり、プロセスが accept を追加するかどうかは、Nginx が制御します。イベント。
Nginx は、ngx_accept_disabled という変数を使用して、accept_mutex ロックを競合するかどうかを制御します。
コードの最初の部分では、ngx_accept_disabled の値を計算します。この値は、単一の Nginx プロセスの接続総数の 8 分の 1 です。アイドル状態の接続の残りの数を引きます。結果の ngx_accept_disabled には、パターンでは、残りの接続数が総接続数の 1/8 未満の場合、その値は 0 より大きくなり、残りの接続数が少ないほど、この値は大きくなります。
コードの 2 番目の部分を見てください。ngx_accept_disabled が 0 より大きい場合、accept_mutex ロックを取得しようとせず、ngx_accept_disabled を 1 ずつデクリメントします。したがって、ここで実行されるたびに、ngx_accept_disabled が 1 ずつデクリメントされます。 0未満になるまで1。
accept_mutex ロックを取得しないことは、接続を取得する機会を放棄することと同じです。空き接続が少ないほど、ngx_accept_disable が大きくなり、より多くの機会が与えられるため、他の接続が得られなくなることは明らかです。プロセスがロックを取得する可能性も高くなります。
同意しない場合は、自分の接続が制御され、他のプロセスの接続プールが使用されるように、Nginx は複数のプロセス間の接続のバランスを制御します。
ngx_accept_disabled = ngx_cycle->connection_n / 8 - ngx_cycle->free_connection_n; if (ngx_accept_disabled > 0) { ngx_accept_disabled--; } else { if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) { return; } if (ngx_accept_mutex_held) { flags |= NGX_POST_EVENTS; } else { if (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay) { timer = ngx_accept_mutex_delay; } } }
ここではまず接続について紹介しますが、Nginx における接続とはどのようなものかを知っておいてください。この接続は比較的高度な使用方法です。
以上がNginx接続とは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。