ホームページ  >  記事  >  運用・保守  >  なぜnginxはそんなに速いのでしょうか?

なぜnginxはそんなに速いのでしょうか?

王林
王林転載
2020-10-20 17:25:172797ブラウズ

なぜnginxはそんなに速いのでしょうか?

まず、Nginx がマルチプロセス (シングルスレッド) およびマルチチャネル IO 多重化モデルを使用していることを知っておく必要があります。 I/O 多重化テクノロジを使用する Nginx は、「同時イベント駆動型」サーバーになります。

#(推奨チュートリアル:

nginx チュートリアル)

なぜnginxはそんなに速いのでしょうか?

##マルチプロセス作業モード

# Nginx が起動すると、マスター プロセスと複数の独立したワーカー プロセスが存在します。マスターは外部から信号を受信し、各ワーカー プロセスに信号を送信し、各プロセスが接続を処理します。マスタープロセスはワーカープロセスの実行状態を監視し、ワーカープロセスが異常終了した場合には、自動的に新しいワーカープロセスを起動します。

ワーカー プロセスの数は通常、マシンの CPU コアの数に設定されることに注意してください。ワーカーが増えるとプロセスが CPU をめぐって競合するだけになり、不必要なコンテキストの切り替えが発生するためです。

マルチプロセス モードを使用すると、同時実行率が向上するだけでなく、プロセスを互いに独立させることができます。1 つのワーカー プロセスがハングアップしても、他のワーカー プロセスには影響しません。

Thinging herd現象

メインプロセス(マスタープロセス)は、まずsocket()を通じてリッスンするためのsockファイル記述子を作成し、次にフォークして子プロセス(ワーカー)を生成します。プロセス) を実行すると、子プロセスは親プロセスの sockfd (ソケット ファイル記述子) を継承し、accept() の後に接続記述子 (接続記述子) を作成し、接続記述子を介してクライアントと通信します。

その後、すべての子プロセスは親プロセスの sockfd を継承するため、接続が確立されると、すべての子プロセスが通知を受け取り、接続を確立するために「競争」します。これは「ショック グループ」と呼ばれます。現象"。多数のプロセスがアクティブ化および一時停止され、接続を受け入れられるプロセスは 1 つだけですが、当然、システム リソースが消費されます。

Nginx による雷鳴の群れ現象の処理

Nginx は、accept のために追加された共有ロックである accept_mutex を提供します。つまり、各ワーカープロセスは accept を実行する前にロックを取得する必要があり、取得できない場合は accept() の実行を諦めます。このロックを使用すると、同時に 1 つのプロセスのみが accpet() を実行するため、激しい群れの問題は発生しません。 accept_mutex は、明示的にオフにできる制御可能なオプションで、デフォルトでオンになっています。

Nginx プロセスの詳細説明

Nginx を起動すると、マスター プロセスと複数のワーカー プロセスが存在します。

マスター プロセス

は、主に次のようなワーカー プロセスを管理するために使用されます。

外部からのシグナルの受信、各ワーカー プロセスへのシグナルの送信、実行状態では、ワーカー プロセスが (異常な状況下で) 終了すると、新しいワーカー プロセスが自動的に再起動されます。

マスター プロセスは、プロセス グループ全体とワーカー プロセス間の対話型インターフェイスとして機能します。ユーザーを監視し、同時にプロセスを監視します。ネットワーク イベントを処理する必要はなく、ビジネスの実行も担当せず、サービスの再起動、スムーズなアップグレード、ログ ファイルの置換、リアルタイムで有効になる構成ファイルなどの機能を実装するためのワーカー プロセスを管理するだけです。

nginx を制御するには、kill を通じてマスター プロセスにシグナルを送信するだけです。たとえば、kill -HUP pid は、nginx を正常に再起動するように nginx に指示します。通常、このシグナルは nginx を再起動するか、設定をリロードするために使用されますが、正常に再起動されるため、サービスは中断されません。 HUP 信号を受信した後、マスター プロセスは何をしますか?

まず、シグナルを受信した後、マスター プロセスは構成ファイルを再読み込みし、新しいワーカー プロセスを開始し、すべての古いワーカー プロセスにシグナルを送信して、名誉あるリタイアが可能であることを伝えます。

古いワーカーは、マスターからシグナルを受信した後、新しいリクエストを受信しなくなり、現在のプロセス内の未処理のリクエストがすべて処理された後、再び終了します。

もちろん、マスター プロセスにシグナルを直接送信するのは古い操作方法であり、nginx バージョン 0.8 以降では、管理を容易にするために一連のコマンド ライン パラメーターが導入されました。たとえば、./nginx -s reload は nginx を再起動し、./nginx -s stop は nginx の実行を停止します。どうやって?リロードを例に挙げると、コマンドの実行時に新しい nginx プロセスが開始され、新しい nginx プロセスがリロード パラメータを解析した後、目的が設定ファイルをリロードするように nginx を制御することであることがわかります。マスター プロセスにシグナルを送信すると、次のアクションはマスター プロセスにシグナルを直接送信した場合と同じになります。

ワーカープロセス

基本的なネットワーク イベントはワーカー プロセスで処理されます。複数のワーカー プロセスはピアツーピアであり、クライアントからのリクエストを平等に競合し、各プロセスは互いに独立しています。リクエストは 1 つのワーカー プロセスでのみ処理でき、ワーカー プロセスは他のプロセスからのリクエストを処理できません。ワーカープロセスの数は設定可能ですが、通常はマシンのCPUコア数に合わせて設定しますが、その理由はnginxのプロセスモデルやイベント処理モデルと切り離すことができません。

ワーカー プロセスは平等であり、各プロセスにはリクエストを処理する同じ機会があります。ポート 80 で http サービスを提供し、接続要求が来た場合、各プロセスが接続を処理する場合があります。まず、マスタープロセスから各ワーカープロセスをフォークし、マスタープロセスではリッスンする必要のあるソケット(listenfd)を確立した後、複数のワーカープロセスをフォークします。新しい接続が到着すると、すべてのワーカー プロセスの listenfd が読み取り可能になります。1 つのプロセスだけが接続を処理できるようにするため、すべてのワーカー プロセスは、listenfd 読み取りイベントを登録する前に、accept_mutex を取得します。mutex を取得するプロセスは、listenfd 読み取りイベントを登録します。接続を受け入れるには、読み取りイベントで accept を使用します。ワーカー プロセスが接続を受け入れると、リクエストの読み取り、解析、リクエストの処理、データの生成を開始し、それをクライアントに返し、最後に接続を切断します。これが完全なリクエストの様子です。リクエストはワーカー プロセスによって完全に処理され、1 つのワーカー プロセスでのみ処理されることがわかります。

ワーカー プロセスのワークフロー

ワーカー プロセスが接続を受け入れると ()、リクエストの読み取り、リクエストの解析、リクエストの処理、およびデータの生成を開始します。次にクライアントに戻り、最後に完全なリクエストを切断します。リクエストは完全にワーカー プロセスによって処理され、1 つのワーカー プロセスでのみ処理できます。

これを行う利点:

ロックによって生じるオーバーヘッドを節約します。各ワーカー プロセスは独立したプロセスであり、リソースを共有せず、ロックも必要ありません。同時に、プログラミングやトラブルシューティングを行う際にも非常に便利になります。独立したプロセスによりリスクが軽減されます。独立したプロセスを使用すると、相互に影響を与えないようにすることができます。1 つのプロセスが終了した後も、他の​​プロセスは引き続き動作しており、サービスは中断されません。マスター プロセスは新しいワーカー プロセスをすぐに再起動します。もちろん、ワーカー プロセスが予期せず終了することもあります。

マルチプロセス モデルでは、各プロセス/スレッドは 1 つの IO チャネルしか処理できません。では、Nginx はどのようにして複数の IO チャネルを処理するのでしょうか?

IO 多重化が使用されていない場合、プロセス内で同時に処理できるリクエストは 1 つだけです (accept() の実行など)。接続がない場合、プログラムは接続が確立されるまでここでブロックされます。接続です。実行を続ける前にここに来てください。

そして多重化により、イベントが発生した場合にのみ制御をプログラムに戻すことができ、それ以外の場合はカーネルがプロセスを一時停止してスタンバイ状態になります。

コア: Nginx が採用した IO 多重化モデルの epoll

#例: Nginx はイベントを登録します: 「新しいクライアントからの接続要求が到着したら、もう一度通知してください」 ", 以降、接続リクエストが来たときのみ、サーバーは accept() を実行してリクエストを受け取ります。別の例として、リクエストを上流のサーバー (PHP-FPM など) に転送し、リクエストが返されるのを待っている場合、処理ワーカーはここでブロックせず、リクエストの送信後にイベントを登録します。データ、教えてください。もう一度読み込みます」というメッセージが表示されるため、プロセスはアイドル状態になり、イベントが発生するのを待ちます。

以上がなぜnginxはそんなに速いのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.imで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。