Node.jsのノンブロッキングまたは非同期I / Oとは何ですか?


136

サーバーサイドJavascriptエンジンのコンテキストでは、ノンブロッキングI / Oまたは非同期I / Oとは何ですか?これは、Javaサーバー側の実装に対する利点として言及されていると思います。


3
この概念を理解するには、ブラウザ環境のスクリプトタグについて考えることが役立ちます。Zakasはこれに関するすばらしい記事を持っています-最初のいくつかのセクションはブロッキングの概念を説明するのに十分でなければなりません:nczonline.net/blog/2010/08/10/what-is-a-non-blocking-script
netpoetica

回答:


317

同期vs非同期

同期実行とは通常、コードが順番に実行されることを指します。非同期実行とは、コードに表示されるシーケンスで実行されない実行を指します。次の例では、同期操作によりアラートが順番に発生します。非同期操作では、alert(2)2番目に実行されているように見えますが、実行されていません。

同期:1、2、3

alert(1);
alert(2);
alert(3);

非同期:1,3,2

alert(1);
setTimeout(() => alert(2), 0);
alert(3);

ブロッキングと非ブロッキング

ブロッキングとは、その操作が完了するまで、以降の実行をブロックする操作を指します。非ブロッキングとは、実行をブロックしないコードを指します。与えられた例でlocalStorageは、は実行を停止して読み取りをブロックする操作です。一方、fetchalert(3)実行から停止しないため、非ブロッキング操作です。

// Blocking: 1,... 2
alert(1);
var value = localStorage.getItem('foo');
alert(2);

// Non-blocking: 1, 3,... 2
alert(1);
fetch('example.com').then(() => alert(2));
alert(3);

メリット

非ブロッキングの非同期操作の利点の1つは、単一のCPUとメモリの使用を最大化できることです。

同期、ブロッキングの例

同期ブロッキング操作の例は、JavaまたはPHPのような一部のWebサーバーがIOまたはネットワーク要求を処理する方法です。コードがファイルまたはデータベースから読み取る場合、コードは実行後のすべてを「ブロック」します。その期間、マシンはメモリを保持し、何も実行していないスレッドの処理時間を保持します。

そのスレッドが停止している間に他の要求に応えるために、ソフトウェアに依存します。ほとんどのサーバーソフトウェアは、追加の要求に応えるために、より多くのスレッドを生成します。これには、より多くのメモリが消費され、より多くの処理が必要になります。

非同期の非ブロッキングの例

Nodeで作成されたような非同期の非ブロッキングサーバーは、1つのスレッドのみを使用してすべての要求を処理します。これは、ノードのインスタンスがシングルスレッドを最大限に活用することを意味します。作成者は、I / Oとネットワーク操作がボトルネックであることを前提に設計しました。

リクエストがサーバーに到着すると、1つずつ処理されます。ただし、サービスされるコードがDBにクエリを実行する必要がある場合などは、コールバックを2番目のキューに送信し、メインスレッドは実行を継続します(待機しません)。DB操作が完了して戻ると、対応するコールバックが2番目のキューから取り出され、3番目のキューに入れられ、そこで実行が保留されます。エンジンが他の何かを実行する機会を得たとき(実行スタックが空になったときなど)、エンジンは3番目のキューからコールバックを取得して実行します。


5
PHPでのブロッキングの 2番目の段落が理解できません。「PHPは通常IOをブロックしますが、OSがIO操作を自動的にスレッド化するため、ブロックしません」と言っていますか?または、これはPHPでは問題ではないと言っていますか?PHPは要求ごとに新しいスレッドを自動的に作成するため、1つのブロックされた要求がPHP環境全体を停止させることはありませんか?(私は後者を推測しています。)
dcow

6
後者です。
ジョセフ

2
待って、後者の場合は、非ブロッキングI / O PHP(reactPHPなど)がブロッキングI / O PHPに比べてどのような利点があるか。まだ混乱しています
Sunu Pinasthika Fajar 2013

5
@CharlieParkerはい。非同期操作はコードと並行して実行されます。ただし、非同期操作の結果に「戻る」ためのコールバックは、メインコードがビジー状態でないときにメインコードで実行するためにキューに入れられます。
ジョセフ

2
@CharlieParkerこれは、非同期メカニズムの内部について詳しく扱っている投稿です。
ジョセフ

7
var startTime = new Date().getTime();
var getEndTime = () => {
    var tempEndTime = new Date().getTime();
    var second = (tempEndTime - startTime)/1000
    return `took ${second} sec...to finish\n`
}

console.log('1: start App', getEndTime())
setTimeout(()=>{
    console.log('2: setTimeout', getEndTime())
}, 1000)
console.log('3: End App', getEndTime())

// console -> Process Order:  1 -> 3 -> 2

コード例

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.