Nginxが非常に高速になる理由を理解しようとしていますが、いくつか質問があります。
私が理解しているように、Apacheは各リクエストを処理するために新しいプロセスを生成しますOR各リクエストを処理するために新しいスレッドを生成します。新しいスレッドはそれぞれ仮想アドレス空間を共有するため、メモリ使用量は増加し続けます。多数の同時リクエストが着信します。
Nginxは、単一の実行スレッドと2つまたは3つ(数は構成可能)のワーカープロセスを備えたリスニングプロセス(マスター)を1つだけ持つことで、これを解決します。このマスタープロセス/スレッドはイベントループを実行しています。着信要求を効果的に待機します。リクエストが届くと、そのリクエストがワーカープロセスの1つに渡されます。
上記の理解が正しくない場合は訂正してください
上記が正しければ、いくつか質問があります。
1.)ワーカープロセスは複数のスレッドを生成し、Apacheと同じ問題に遭遇しませんか?
2.)または、イベントベースのアーキテクチャがすべての下にノンブロッキングIOを使用しているため、nginxは高速です。たぶん、ワーカープロセスはonlynon-blocking-IOを実行するスレッドを生成します、それはそれですか?
3.)「正確に」は「イベントベースのアーキテクチャ」です。私のようなソエモネが理解できるように、誰かがそれを本当に単純化できますか。それはnon-blocking-ioまたは他の何かにも関係していますか?
c10k の参照を取得しました。これを実行しようとしていますが、イベントベースについては考えていません。アーチ。ノンブロッキングIOの方が多いようです。
概念的な観点からはそれほど複雑ではありません。明確にしようとしますが、いくつかの単純化を行う必要があります。
イベントベースのサーバー( nginx や lighttpd など)は、イベント監視システムのラッパーを使用します。例えば。 lighttpdは libevent を使用して、より高度な高速イベント監視システムを抽象化します( libev も参照)。
サーバーは、接続ごとに単純なステートマシンを使用して、サーバーが持つすべての非ブロッキング接続(書き込みと読み取りの両方)を追跡します。イベント監視システムは、新しいデータが利用可能になったとき、またはサーバーがさらにデータを書き込むことができるときに、サーバープロセスに通知します。ソケットプログラミングを知っているなら、それはステロイドのselect()
のようなものです。サーバープロセスは、可能な場合はsendfile()
などの高度な関数を使用して要求されたファイルを送信するか、通信用のソケットを使用してCGIプロセスに要求を送信します(このソケットは他のソケットと同様にイベント監視システムで監視されます)ネットワーク接続。)
This 念のため、nginxの内部に関する多くの優れた情報としてリンクします。お役に立てば幸いです。
Apacheは複数のスレッドを使用して、各リクエストに独自の実行スレッドを提供します。これは、同期I/Oを使用するときにブロッキングを回避するために必要です。
Nginxは非同期I/Oのみを使用するため、ブロッキングは問題になりません。 nginxが複数のプロセスを使用する唯一の理由は、マルチコア、マルチCPU、およびハイパースレッディングシステムを最大限に活用することです。 SMPをサポートしていても、カーネルは複数のCPUで単一の実行スレッドをスケジュールすることはできません。論理CPUごとに少なくとも1つのプロセスまたはスレッドが必要です。
したがって、違いは、nginxはSMPの利点を最大限に活用するためにのみの十分なワーカープロセスを必要とするのに対し、Apacheのアーキテクチャは必要ですリクエストごとに新しいスレッド(それぞれが約8MBの独自のスタックを持つ)を作成します。明らかに、同時実行性が高い場合、Apacheははるかに多くのメモリを使用し、多数のスレッドを維持することでより大きなオーバーヘッドが発生します。
Apacheは、リクエストごとに新しいスレッドを生成しません。スレッドのキャッシュ、またはリクエストをファームアウトする事前にフォークされたプロセスのグループを維持します。同時リクエストの数は子/スレッドの数によって制限されますはい、しかしApacheはすべてのリクエストに対して新しいスレッド/子を生成していません。これは途方もなく遅くなります(スレッドを使用しても、すべてのリクエストの作成と破棄は非常に遅くなります)
Nginxはマスターワーカーモデルを使用します。マスタープロセスは、構成のロードとワーカーの作成/破棄/保守を処理します。 Apacheのように、それはすでに実行されているいくつかの事前にフォークされたプロセスから始まり、それぞれがワーカーです(そしてそのうちの1つは「マスター」プロセスです)。各ワーカープロセスは、リスニングソケットのセットを共有します。各ワーカープロセスは接続を受け入れて処理しますが、ワーカーごとに1つの接続しか処理できないApacheとは異なり、各ワーカーは一度に数千の接続を処理できます。
Nginxがこれを実現する方法は、「多重化」によるものです。 libeventを使用せず、nginx専用に設計され、nginxソフトウェアの開発とともに開発が進んだカスタムイベントループを使用します。多重化は、ループを使用して、1つのデータ/新しい接続/接続ごとに何でも/ループの反復ごとにオブジェクトを操作するチャンクごとにプログラムチャンクを「インクリメント」することによって機能します。これはすべて、Epoll()kqueue()やselect()などのバックエンドに基づいています。どちらを読むべきか