Node.jsがシングルスレッドになるのはなぜですか?[閉まっている]


255

PHP(またはJava / ASP.NET / Ruby)ベースのWebサーバーでは、すべてのクライアント要求が新しいスレッドでインスタンス化されます。しかし、Node.jsでは、すべてのクライアントが同じスレッドで実行されます(同じ変数を共有することさえできます!)I / O操作はイベントベースであるため、メインスレッドのループをブロックしないことを理解しています。

私が理解していないのは、Nodeの作成者がシングルスレッドを選択した理由は何ですか?それは物事を困難にします。たとえば、メインスレッドをブロックする(そして新しいクライアント要求がブロックされる)ため、CPU集中型の関数を実行できないため、プロセスを生成する必要があります(つまり、別のJavaScriptファイルを作成して別のノードプロセスを実行する必要があります)それ)。ただし、PHPでは、CPUを集中的に使用するタスクは他のクライアントをブロックしません。マルチスレッドWebサーバーと比較した場合の利点は何ですか?

注:私はこれを回避するためにクラスタリングを使用しましたが、それはきれいではありません。


12
私は最近、Nodeの背後にある理論のいくつかを説明する優れたビデオ(29分)を視聴しました。:私もCPU集約型のタスクとそれらを処理する方法について簡単にについての男の話だと思うyoutube.com/watch?v=L0pjVcIsU6A
— whirlwin

24
あなたはこれを知っているかもしれませんが、明確に言うと、Node.jsはシングルスレッドではありません。JavaScriptコードはシングルスレッドで実行されますが、プラグインが実行できるIO操作などはスレッドプールで実行されます。Node.jsは、マルチスレッドコードを処理しなくても、マルチスレッドの利点の多くを提供します。また、Node.jsの寄稿者は、JavaScriptの作成者が選択した、JavaScriptのシングルスレッドの性質を選択しませんでした。JSがマルチスレッドコンテキストで動作する方法を考えることはできませんが、たとえあったとしても、V8は、Node.jsがJavaScriptエンジンとして使用する方法で記述されていません。
— ブラッド

5
PHPはJavaScriptよりもシングルスレッドです。あなたはおそらくFastCGIやmod_phpのようなサーバーモジュールを考えています。つまり、Node.jsは、PHP、Java、Rubyではなく、Apache、Nginx、またはIISと実際に比較しています。
— アルバロゴンサレス

34
ノードはシングルスレッドではありません。それは人気のある誤解です。単純なシステムでも、5つのスレッドがnode -e 'setTimeout(()=>{},1000);' & ps -T h $! | wc -l; kill $!表示されます。メインイベントループはシングルスレッドです(そうでなかったとしてもあまり意味がありません)が、Nodeはマルチスレッド化されており、必要に応じてマルチスレッドのシングルプロセスアプリケーションを作成できます。私はそれについて包括的な答えを書きたいと思いますが、私ができないようにあなたの質問を閉じることに決めた人もいます。再開することに投票します。投票数が増えて再開された場合は、コメントで教えてください。
— rsp

2
@rspコメントに感謝しますが、メインスレッドではI / O関連ではありません。何かを行う大きなforループのようなCPU関連のことをしている場合、サーバーは接続の処理を停止します。つまり、その時点ではサーバーは使用できません。ほとんどのサーバーのように本質的にすべての接続をスレッド化する代わりに、クラスターのようなハックを使用して、単純なことをします。jxcore.comはこれに対処しようとしましたが、特別な/変更されたノードプラグインを使用するため、基本的に使用できません。
— foreyez 2016

回答:


292

Node.jsは、非同期処理の実験として明示的に作成されました。理論は、単一のスレッドで非同期処理を行うと、通常のスレッドベースの実装よりも、通常のWeb負荷でより高いパフォーマンスとスケーラビリティを提供できるというものでした。

そして、あなたは何を知っていますか?私の意見では、理論は裏付けられています。CPU集中型の処理を実行していないnode.jsアプリは、Apache、IIS、または他のスレッドベースのサーバーよりも数千の同時接続を実行できます。

シングルスレッドの非同期の性質は、物事を複雑にします。しかし、正直に言うと、スレッド化よりも複雑だと思いますか?1つの競合状態が月全体を台無しにする可能性があります!または、どこかで設定が原因でスレッドプールを空にして、クロールに対する応答時間が遅いのを確認してください!デッドロック、優先順位の逆転、およびマルチスレッド化に伴うその他すべての旋回は言うまでもありません。

結局、私はそれが普遍的に良くも悪くもないと思います。それは違います、そして時にはそれはより良いこともあり、そうでないこともあります。ジョブに適したツールを使用します。


26
しかし、Webサーバーは通常、CPU集中型の処理をALOTに実行しますが、データベースをフェッチするだけではありません。クライアントに提供する前に、フェッチしたものを処理し、多くの時間で多くのビジネスロジックを実行する必要があります。
— foreyez 2013

22
つまり、ワーカーをスポーンするだけです。これでNode.jsとの取り引きは完了です。重いものは別のプロセスで実行でき、それを処理すると軽量のコールバックになります。
— MaiaVictor 2013

7
その問題は、ワーカーごとにosレベルのプロセスが実行されていることです。「ps」コマンドを使用すると、プロセスが表示されます。つまり、マシン上で一度に数千のプロセスが実行される可能性があるということです。
— foreyez 2013

9
@foreyez、ユーザーごとのプロセスは必要ありません。負荷を分割する方法を選択できます。また、誰もが大量のCPUを集中的に使用しているわけではありません。ノードは仕事のためのツールです...多分あなたの仕事ではなく、多くの種類の仕事。
— ブラッド

15
実際には、@ foreyezが「Webサーバーは通常、CPU集約的なもののALOT(sic)に対応している」という声明をバックアップしてほしいと思います。私の経験ではそうではありません。あるいは、「CPU集約的」の私の定義が彼の定義と異なるかもしれません。製品データをUIに変換することは、CPUに負荷をかけず、注文の計算なども行いません。ウェブのほとんどはかなりトランザクションです。CPU集中型のものは、ビデオの変換、画像形式の変換などです。その多くは、実際にはノードがかなりうまく機能しているファイルI / Oによるものです。また、変換専用の別のプロセスに簡単にオフロードできます。
— ポール

62

サーバーの「リクエストごとに1つのスレッド」モデルの問題は、イベントループスレッドモデルと比較して、いくつかのシナリオで適切にスケーリングされないことです。

通常、I / O集中型のシナリオでは、リクエストはI / Oが完了するのを待つほとんどの時間を費やします。この間、「リクエストごとに1つのスレッド」モデルでは、スレッドにリンクされたリソース(メモリなど)は使用されず、メモリが制限要因になります。イベントループモデルでは、ループスレッドは次のイベント(I / O終了)を選択して処理します。したがって、スレッドは常にビジーです(もちろん、正しくプログラムした場合)。

すべてが新しいように見えるイベントループモデルとすべての問題の解決策ですが、どのモデルを使用するかは、取り組む必要のあるシナリオによって異なります。集中的なI / Oシナリオ(プロキシなど)がある場合は、イベントベースモデルが適用されますが、同時プロセス数が少ないCPU集中的なシナリオは、スレッドベースのモデルで最適に機能します。

現実の世界では、ほとんどのシナリオは少し真ん中にあります。スケーラビリティの実際のニーズと開発の複雑さのバランスをとって、正しいアーキテクチャを見つける必要があります(たとえば、CPU集中型タスクのバックエンドに委任するイベントベースのフロントエンドがあります。フロントエンドは、タスクを待機しているリソースをほとんど使用しません結果。)他の分散システムと同様に、機能させるためには多少の努力が必要です。

どんなシナリオにも苦労せずに合う銀の弾丸を探しているなら、あなたはあなたの足に弾丸を置くことになります。


8
Node.jsは、v8マルチスレッドのサポートがないため、イベントのみの処理に制限されています。ええと、JavaScript言語自体には必要な機能がないため、実装はすべてトリッキーになります。私の意見では、それがNode.jsの主な原因です。他の言語では、必要なものを選択できます。または、java NIOなどの両方のモデルのハイブリッド。
— FrameGrace 14

2
@Kazaag、最新のWebサーバーはスレッドプールを維持します。それらは、ページの読み込みごとに新しいスレッドを単純に生成するだけではありません。これらは古いWebサーバーです。
— Pacerier

1
@Pacerier新しいスレッドが生成されるとは言わなかったが、リクエストが完了するまで、各スレッドは1つのリクエストに割り当てられる。
— Kazaag

2
@Kazaag「リクエストが完了するまで、各スレッドが1つのリクエストに割り当てられる」というのは、一般的なルールではありません。つまり、.Net(HTTPリクエストの処理を含む)では、非同期(タスクベース)プログラミングを使用できます。これにより、I / Oおよびその他の非同期操作が完了するのを待つ間、スレッドが解放されます。これは、MVC / APIコントローラなどの高レベルのプログラミングにも適用できます。そのため、実際には、保留中のHTTPリクエストは20ですが、アクティブなスレッドは1つだけです。
— user3285954 2018年

29

要するに、ノードは内部的にシングルスレッドであるV8から引き出されます。CPU集中型タスクの制約を回避する方法があります。

ある時点(0.7)で、作成者は複数の計算スレッドを実装する方法として分離を導入しようとしましたが、最終的には削除されました:https : //groups.google.com/forum/#!msg / nodejs / zLzuo292hX0 / F7gqfUiKi2sJ


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