Node.jsが数千のリクエストを処理する方法
Node.jsはシングルスレッドだと言われます。
それなのに、停止することなく数千のリクエストを処理し、ファイルを読み込み、APIコールを行います。
どうやって実現しているのでしょうか?
その答えはlibuvです。
libuvはC言語のライブラリです。これにより、Node.jsは非同期かつノンブロッキングなI/O機能を持つことができます。JavaScript単体では、ファイルの読み込みやネットワークソケットの管理を行うことはできません。Node.jsはlibuvを使用してオペレーティングシステムと通信します。
libuvがなければ、ファイルを読み込むたびにJavaScriptは停止してしまいます。アプリケーションは応答不能になるでしょう。
libuvがあれば、ファイルの読み込みはバックグラウンドで行われます。JavaScriptは他のコードの実行を継続できます。
例:
console.log("Start");
fs.readFile("data.txt", "utf8", (err, data) => {
console.log(data);
});
console.log("End");
出力: Start End (ファイルの内容)
Node.jsはファイルの読み込みが完了する前に「End」を出力します。待機はしません。
libuvがコードを管理する方法:
• イベントループ (The Event Loop): libuvはタスクが完了したかどうかを確認するループを実行します。タスクが完了すると、コールバックをキューに追加します。 • スレッドプール (Thread Pool): JavaScriptは1つのスレッドを使用しますが、libuvはワーカー・スレッドのプールを使用します。デフォルトでは、このプールには4つのスレッドがあります。これらのスレッドは、以下のような重いタスクを処理します:
- ファイルシステムの操作
- DNSルックアップ
- 圧縮
- 暗号化
• ネットワーキング (Networking): libuvはHTTP、TCP、UDPソケットを管理します。これにより、サーバーは一度に多くの接続を処理できます。
• タイマー (Timers): libuvは
setTimeoutとsetIntervalを処理します。
実行フローは次のようになります:
- JavaScriptがコードを実行します。
- libuvが重いタスクをバックグラウンドに送ります。
- JavaScriptは次の行の実行を続けます。
- タスクが完了すると、libuvがイベントループに通知します。
- イベントループがコールバックを実行します。
ピザ屋を例に考えてみましょう。
libuvがなければ、あなたはカウンターに立ち、「料理はできましたか?」と10秒ごとに聞き続けます。これでは列を止めてしまうことになります。
libuvがあれば、注文をして席に座り、通知を待ちます。ピザができるまで、他のことをして自由に過ごせます。
まとめ:
• JavaScriptの実行: V8 Engine • イベントループ: libuv • ファイルI/O: libuv • ネットワーク: libuv • タイマー: libuv
libuvはNode.jsの高速性を維持するエンジンです。
