[解決済み] スレッドプールはどのような場合に使用するのですか?
質問
Node.jsがどのように動作するか理解しています。イベントを受信し、それをワーカープールに委譲する単一のリスナースレッドを持っています。ワーカスレッドは、それが仕事を完了するとリスナーに通知し、リスナーは呼び出し元への応答を返します。
私の質問はこれです:私がNode.jsでHTTPサーバーを立ち上げ、私のルーティングされたパスイベントの1つ(たとえば"/test/sleep")でsleepを呼び出すと、システム全体が停止してしまいます。単一のリスナースレッドでさえも。しかし、私の理解は、このコードがワーカープールで起こっていることでした。
さて、対照的に、私が Mongoose を使用して MongoDB と話をするとき、DB の読み取りは高価な I/O 操作です。Node はその作業をスレッドに委譲し、完了したらコールバックを受け取ることができるようです。DB からの読み込みにかかる時間は、システムをブロックしないようです。
Node.jsはどのようにリスナースレッドに対してスレッドプールスレッドを使用することを決定するのでしょうか?なぜ、スリープし、スレッドプールスレッドのみをブロックするイベントコードを書くことができないのでしょうか?
どのように解決するのですか?
node がどのように動作するかについてのあなたの理解は正しくありません...しかし、それはよくある誤解です。なぜなら、状況の現実は実際にはかなり複雑で、通常、物事を過度に単純化する "node is single threaded" といった小難しいフレーズにまで煮詰めてしまうからです。
当面の間、次のような明示的なマルチプロセシング/マルチスレッドを無視します。 クラスター と ウェブワーカー・スレッド を追加し、典型的な非スレッドノードについて話すだけです。
Node は単一のイベントループで実行されます。 これはシングルスレッドで、あなたはその1つのスレッドしか得ることができません。 あなたが書いたすべての javascript はこのループで実行され、そのコードでブロック操作が発生すると、ループ全体がブロックされ、それが終了するまで何も起こりません。 これが、よく耳にするnodeの典型的なシングルスレッド的な性質です。 しかし、これは全体像ではありません。
特定の関数やモジュール(通常は C/C++ で書かれている)は、非同期 I/O をサポートします。 これらの関数やメソッドを呼び出すと、ワーカスレッドに呼び出しを渡すことを内部的に管理します。 例えば
fs
モジュールを使ってファイルをリクエストすると
fs
モジュールはその呼び出しをワーカスレッドに渡し、ワーカーはその応答を待ち、その間にそれなしで動いていたイベントループにそれを返します。 このすべてはノード開発者からは抽象化され、モジュール開発者からは
libuv
.
Denis Dollfus がコメントで指摘しているように (
この回答
からのコメント) にあるように、非同期 I/O を実現するために libuv が使用する戦略は、必ずしもスレッドプールではありません。
http
モジュールの場合、現時点では別の戦略が使用されているようです。ここでの目的では、非同期コンテキストが (libuv を使用して) どのように実現されるか、そして libuv によって維持されるスレッドプールは非同期性を実現するためにそのライブラリによって提供される複数の戦略の 1 つであるということに主に注目することが重要です。
ほぼ関連する余談ですが、ノードがどのように非同期性を達成するか、また、関連する潜在的な問題とその対処法について、より深い分析があります。 この素晴らしい記事で . そのほとんどは、私が上で書いたことを拡大したものですが、さらに指摘することもあります。
- ネイティブ C++ および libuv を使用するプロジェクトにインクルードする外部モジュールは、スレッド プールを使用する可能性があります (データベース アクセスを考えてみてください)。
- libuv はデフォルトで 4 のスレッドプールサイズを持ち、スレッドプールへのアクセスを管理するためにキューを使用します - その結果、5 つの長時間実行する DB クエリをすべて同時に実行すると、それらの 1 つ (とスレッドプールに依存するその他の非同期アクション) は、それらのクエリが開始する前に終了するのを待っていることになります。
-
メソッドを使用してスレッド プールのサイズを大きくすることで、これを軽減することができます。
UV_THREADPOOL_SIZE
環境変数を使用することで、スレッドプールが必要となり作成される前に実行することができます。process.env.UV_THREADPOOL_SIZE = 10;
node で伝統的なマルチプロセッシングやマルチスレッドが必要な場合は、ビルトインの
cluster
モジュールや他の様々なモジュール、例えば前述の
webworker-threads
を使うか、あるいは作業をチャンクアップする何らかの方法を実装して、手作業で
setTimeout
または
setImmediate
または
process.nextTick
を使うことで、作業を一時停止し、他の処理が完了するのを待ってからループで作業を続けることができます(ただし、これは推奨されません)。
もしあなたがjavascriptで長時間実行/ブロックするコードを書いているのなら、おそらく間違いであることに注意してください。 他の言語の方がはるかに効率的に実行できます。
関連
-
webpack ENOENTソリューションの起動
-
[解決済み】npm 5で作成されたpackage-lock.jsonファイルはコミットするのでしょうか?
-
[解決済み] package.jsonのチルダ(~)とキャレット(^)の違いは何ですか?
-
[解決済み] npm installの-saveオプションは何ですか?
-
[解決済み] インストールされているnpmパッケージのバージョンを検索する
-
[解決済み] npm package.jsonファイルのdependencies, devDependencies, peerDependenciesの違いは何ですか?
-
[解決済み] package.jsonの各依存関係を最新バージョンに更新する方法は?
-
[解決済み] Node.jsを使うタイミングをどう判断するか?
-
[解決済み] 一般的に、Node.jsは10,000の同時リクエストをどのように処理するのですか?
-
[解決済み】Node.jsは内部でThreadsに依存しているのに、どうして本質的に高速なのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Node Version Manager のインストール - nvm コマンドが見つかりません。
-
[解決済み】MongooseでEnumを作成し使用する方法
-
[解決済み】Mongooseで、日付でソートするにはどうしたらいいですか?(node.js)
-
[解決済み】NPMインストールエラー:解析中の予期せぬJSON入力の終了 '...nt-webpack-plugin": "0'' 付近。
-
[解決済み】npm 5で作成されたpackage-lock.jsonファイルはコミットするのでしょうか?
-
[解決済み] EventEmitter のメモリリークの可能性が検出された
-
[解決済み] joiライブラリを使用して2つの時間を比較する方法
-
[解決済み] nvm は npm config の "prefix" オプションと互換性がありません。
-
[解決済み] エラーです。Cannot find module 'ejs'
-
[解決済み] エラーです。Expressでビューの検索に失敗しました