1. ホーム
  2. node.js

[解決済み】Node.jsのシングルスレッド・ノンブロッキングIOモデルの動作について

2022-03-25 13:57:50

質問

私はNodeのプログラマーではありませんが、以下のことに興味があります。 シングルスレッド・ノンブロッキングIOモデル が動作します。 記事を読んだ後 ノードJSイベントループの理解 本当に困っているんです。 このモデルには例があります。

c.query(
   'SELECT SLEEP(20);',
   function (err, results, fields) {
     if (err) {
       throw err;
     }
     res.writeHead(200, {'Content-Type': 'text/html'});
     res.end('<html><head><title>Hello</title></head><body><h1>Return from async DB query</h1></body></html>');
     c.end();
    }
);

ケです。 スレッドが1つしかないので、リクエストA(先に来る)とBがある場合、サーバー側のプログラムはまずリクエストAを処理します:SQLクエリを実行すると、I/O待ちのために文が眠っています。そして、プログラムは I/O を待つことになり、後ろにあるウェブページをレンダリングするコードを実行することができません。待ち時間の間、プログラムはリクエストBに切り替わるのでしょうか?私の考えでは、シングルスレッド・モデルのため、あるリクエストと別のリクエストを切り替える方法はありません。しかし、サンプルコードのタイトルには、次のように書かれています。 あなたのコード以外はすべて並列に実行されます。 .

(追記)私はコードを理解したことがないので、誤解しているかどうかわかりません。 Nodeは使ったことがありません)待ち時間にどのようにAからBに切り替えるのでしょうか?また を説明してください。 シングルスレッド・ノンブロッキングIOモデル のNodeをわかりやすく 簡単な方法ですか?お教えいただけると幸いです :)

解決するには?

Node.jsは libuv これは、サポートされているOS(少なくともUnix、OS X、Windows)が提供する非同期(ノンブロッキング)入出力のためのAPI/シスコー ルを抽象化したクロスプラットフォームライブラリです。

非同期IO

このプログラミングモデルでは、ファイルシステムが管理するデバイスやリソース(ソケット、ファイルシステムなど)に対するオープン/リード/ライト操作が可能です。 呼び出したスレッドをブロックしない (典型的な同期C言語モデルのように)新しいデータやイベントが利用可能になったときに通知されるように(カーネル/OSレベルのデータ構造で)プロセスをマークするだけです。Webサーバーのようなアプリの場合、プロセスは通知されたイベントがどのリクエスト/コンテキストに属するかを把握し、そこからリクエストの処理を進める責任を負います。この場合、OS にリクエストを出したスタックフレームとは別のスタックフレームにいることになることに注意してください。

関数Aでリクエストを行い、その結果を別の関数で処理する必要がありますが、通常、関数Aからのローカルは使用できません。

ノードのモデル(継続受け渡しスタイルとイベントループ)

Nodeはjavascriptの言語機能を利用して、プログラマに特定のプログラミングスタイルを採用させることで、このモデルをもう少し同期的に見せるという問題に取り組んでいます。IOを要求するすべての関数は、以下のようなシグネチャを持っています。 function (... parameters ..., callback) そして、要求された操作が完了したときに呼び出されるコールバックを与える必要があります (ほとんどの時間は、OS が完了を通知するのを待つために費やされていることに留意してください - その時間は他の作業に費やすことができます)。Javascriptのクロージャのサポートにより、外側の(呼び出す)関数で定義した変数をコールバックの本体内で使用することができます。これにより、ノードのランタイムによって呼び出される異なる関数間で状態を独立して保持することができます。参照 継続受け渡しスタイル .

さらに、IOオペレーションを発生させる関数を呼び出した後、呼び出し側の関数は通常 return を制御し、ノードの イベントループ . このループは、実行が予定されていた次のコールバックや関数を呼び出します(ほとんどの場合、対応するイベントがOSから通知されたからです) - これによって、複数のリクエストを同時に処理することができます。

nodeのイベントループは次のように考えることができます。 カーネルのディスパッチャに似ている カーネルはブロックされたスレッドの保留中のIOが完了した時点で実行をスケジュールし、ノードは対応するイベントが発生した時点でコールバックをスケジュールします。

高度な並行処理、並列処理なし

最後に、quot;everything runs in parallel except your code"というフレーズは、nodeがあなたのコードに以下のリクエストを処理させるという点を適切にとらえています。 何十万ものソケットをシングルスレッドでオープン すべての js ロジックを単一の実行ストリームで多重化およびシーケンス化することによって、同時に実行します(ここで "everything runs in parallel" というのはおそらく正しくないのですが - 参照してください)。 並行処理と並列処理 - 違いは何ですか? ). これはウェブアプリサーバーではかなり有効です。なぜなら、ほとんどの時間は実際にネットワークやディスク(データベース/ソケット)の待ち時間に費やされ、ロジックはそれほどCPUに負荷がかからないからです - つまり。 これは、IOバウンドワークロードのためにうまく機能します。 .