Webサーバーの詳細を理解しようとしています。Apacheなどのサーバーが継続的に新しいリクエストをポーリングしているのか、それとも何らかの割り込みシステムで動作するのか疑問に思っています。割り込みの場合、割り込みを引き起こしているのはネットワークカードドライバーですか?
Webサーバーの詳細を理解しようとしています。Apacheなどのサーバーが継続的に新しいリクエストをポーリングしているのか、それとも何らかの割り込みシステムで動作するのか疑問に思っています。割り込みの場合、割り込みを引き起こしているのはネットワークカードドライバーですか?
回答:
簡単な答えは、ある種の割り込みシステムです。基本的に、これらはブロッキングI / Oを使用します。つまり、新しいデータを待っている間、スリープ(ブロック)します。
サーバーはリッスンソケットを作成し、新しい接続を待つ間ブロックします。この間、カーネルはプロセスを割り込み可能なスリープ状態にし、他のプロセスを実行します。これは重要なポイントです。プロセスポーリングを継続的に行うと、CPUが無駄になります。カーネルは、実行する作業があるまでプロセスをブロックすることにより、システムリソースをより効率的に使用できます。
新しいデータがネットワークに到着すると、ネットワークカードは割り込みを発行します。
ネットワークカードから割り込みが発生すると、カーネルはネットワークカードドライバーを介して、ネットワークカードから新しいデータを読み取り、メモリに保存します。(これは迅速に行う必要があり、通常は割り込みハンドラー内で処理されます。)
カーネルは、新しく到着したデータを処理し、それをソケットに関連付けます。そのソケットでブロックしているプロセスは実行可能とマークされ、実行可能になります。必ずしもすぐに実行されるとは限りません(カーネルが他のプロセスを実行することを決定する場合があります)。
余暇に、カーネルはブロックされたWebサーバープロセスを起動します。(現在は実行可能であるため。)
Webサーバープロセスは、時間が経過していないかのように実行を続けます。そのブロッキングシステムコールが戻り、新しいデータを処理します。次に...手順1に進みます。
accept
。それらは(幸運なことに、または完全にダメでしょう!)独立した、非同期に実行されるタスクです。接続が入ると、接続はキューに入れられ、そこaccept
からプルされます。存在しない場合のみ、ブロックします。
かなり多くの「より低い」詳細があります。
まず、カーネルにはプロセスのリストがあり、いつでもこれらのプロセスの一部は実行中であり、一部は実行されていないことを考慮してください。カーネルは、実行中の各プロセスにCPU時間のスライスを許可し、それを中断して次のプロセスに移動します。実行可能なプロセスがない場合、カーネルはおそらくHLTなどの命令をCPUに発行し、ハードウェア割り込みが発生するまでCPUを一時停止します。
サーバー内のどこかに、「何かすることがあります」というシステムコールがあります。これを行う方法には、大きく2つのカテゴリがあります。Apacheの場合accept
、おそらくポート80でリッスンしているApacheが以前に開いたソケットを呼び出します。カーネルは接続試行のキューを維持し、TCP SYNを受信するたびにそのキューに追加します。カーネルがTCP SYNを受信したことをどのように認識するかは、デバイスドライバーによって異なります。多くのNICでは、ネットワークデータを受信したときにおそらくハードウェア割り込みが発生します。
accept
次の接続開始を返すようカーネルに要求します。キューが空ではなかった場合は、accept
すぐに戻ります。キューが空の場合、プロセス(Apache)は実行中のプロセスのリストから削除されます。後で接続が開始されると、プロセスが再開されます。これは「ブロック」と呼ばれます。これを呼び出すプロセスにとって、accept()
結果が得られるまで戻らない関数のように見えるためです。その間、プロセスは他に何もできません。
いったんaccept
戻って、Apacheのは、誰かが接続を開始しようとしていることを知っています。次にforkを呼び出して、Apacheプロセスを2つの同一のプロセスに分割します。これらのプロセスの1つはHTTP要求の処理に進み、他のプロセスaccept
は次の接続を取得するために再度呼び出します。したがって、常にaccept
サブプロセスを呼び出して生成するだけのマスタープロセスがあり、各要求に対して1つのサブプロセスがあります。
これは単純化です。プロセスの代わりにスレッドを使用してこれを行うことができます。またfork
、要求を受信するとすぐにワーカープロセスを準備できるようにして、起動のオーバーヘッドを削減することもできます。Apacheの構成方法に応じて、これらのいずれかを実行できます。
これは、その方法の最初の広範なカテゴリであり、ソケットを操作するシステムや呼び出しは、何かを返すまでプロセスを一時停止するため、ブロッキングIOと呼ばれます。accept
read
write
他の大まかな方法は、ノンブロッキングまたはイベントベースまたは非同期IOと呼ばれます。これは、のようなシステムコールを用いて実装されますselect
かepoll
。これらはそれぞれ同じことを行います:ソケット(または一般的にはファイル記述子)のリストとそれらの処理を指定し、カーネルはそれらのいずれかを実行する準備ができるまでブロックします。
このモデルではepoll
、「ポート80に新しい接続があるか、開いているこれらの9471他の接続のいずれかを読み取る新しいデータがある場合、教えてください」とカーネルに伝えることができます。epoll
それらのいずれかの準備が整うまでブロックし、それを実行します。その後、繰り返します。accept
andのようなシステムコール、read
およびwrite
ブロックepoll
することはありません。その理由の1つは、コールするたびに、準備ができているのでブロックする理由がないことを通知したためです。非ブロッキングモードでは、これらの呼び出しはEWOULDBLOCK
ブロッキングの代わりに失敗します。
このモデルの利点は、必要なプロセスが1つだけであることです。これは、リクエストごとにスタックとカーネル構造を割り当てる必要がないことを意味します。NginxとHAProxyはこのモデルを使用します。これは、同様のハードウェアでApacheよりも多くの接続を処理できる大きな理由です。