ホームページ >ウェブフロントエンド >jsチュートリアル >クラスタリングとワーカー スレッド - Node JS
前の記事「ノード JS の内部」では、ノード JS の内部アーキテクチャについて説明し、複数のリクエストを同時に処理するためにノードのスレッド プール サイズを増やす必要がある理由についても説明しました。スケーラビリティとパフォーマンスはスレッド プールのサイズに関係がないことをお伝えしました。
スケーラビリティと高いパフォーマンスを実現するために、クラスタリングとワーカー スレッドを使用できます。
あなたが盛大な結婚式に出席していて、何千人ものゲストが出席しているとします。キッチンが 1 つあり、1 人のコックがゲスト全員の食事を準備しています。予測不可能だと思いますよね?料理人が 1 人しかいない場合、キッチンのリソースを最大限に活用することはできません。
これは、すべてのリクエストを処理するために 1 つのコアだけが使用されている場合に、マルチコア CPU 上で実行されている Node JS アプリケーションでまさに起こることです。したがって、私たちのマシンはマルチコアの能力を備えていますが、クラスタリングがなければ、アプリケーションは 1 コアだけで実行されます。 1 つのコアがすべての作業を処理します。
キッチンで複数の調理人が働いているとき、それがクラスタリングです。
クラスタリングは、単一ノードの JS アプリケーションが複数の CPU コアを効果的に利用できるようにするために使用される手法です。
クラスタリングを実装するには、Node JS のクラスター モジュールを使用する必要があります。
const cluster = require('cluster');
このクラスター モジュールを使用すると、Node JS アプリケーションの複数のインスタンスを作成できます。これらのインスタンスはワーカーと呼ばれます。すべてのワーカーは同じサーバー ポートを共有し、受信リクエストを同時に処理します。
クラスター アーキテクチャには 2 種類のプロセスがあります。
1.マスタープロセス:
マスタープロセスは、従業員を管理するキッチンのメインコックのようなものです。アプリケーションを初期化し、クラスタリング環境をセットアップし、タスクをワーカー プロセスに委任します。アプリケーションリクエストを直接処理しません。
マスタープロセスは何をしますか?
cluster.fork() メソッドを使用して複数のワーカー プロセスを作成します。また、ワーカーがクラッシュしたり予期せず終了した場合にも、ワーカーが再起動されます。
受信リクエストがすべてのワーカー プロセスに確実に分散されるようにします。 Linux では、これはオペレーティング システムによって処理され、Windows では、Node JS 自体がロード バランサーとして機能します。
IPC(プロセス間通信)を介したワーカー間の通信を可能にします。
2.ワーカープロセス:
ワーカー プロセスは、マスター プロセスによって作成された Node JS アプリケーションのインスタンスです。各プロセスは個別の CPU コアで独立して実行され、受信リクエストを処理します。
ワーカー プロセスは相互に直接通信できず、マスター経由で通信します。
ワーカー プロセスは受信リクエストを処理し、データベース クエリ、計算、アプリケーション ロジックなどのいくつかのタスクを実行します。
const cluster = require('cluster');
ここでは、最初にこれがマスタープロセスであることを確認しています。 「はい」の場合、ワーカー プロセスが作成されます。
コードでは、cluster.fork() を使用してワーカー プロセスを作成しています。
しかし、これはワーカー プロセスを作成する理想的な方法ではありません。
4 つのワーカー プロセスを作成しており、システムに 2 つのコアがあるとします。
ハードコーディングされたワーカー プロセスを作成するのではなく、この問題を解決するには、まず CPU コアを見つけてから、データがワーカー プロセスを作成すると考えます。
const cluster = require('cluster'); const os = require('os'); if (cluster.isMaster) { console.log(`Master ${process.pid} is running`); // Fork workers cluster.fork(); cluster.fork(); cluster.fork(); cluster.fork(); } else { console.log(`Worker ${process.pid} is running`); // Worker logic (e.g., server setup) goes here }
デュアルコアシステムを使用しているため、出力は次のようになります。
const cluster = require('cluster'); const os = require('os'); if (cluster.isMaster) { console.log(`Master ${process.pid} is running`); const numCPUs = os.cpus().length; // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork(); } } else { console.log(`Worker ${process.pid} is running`); // Worker logic (e.g., server setup) goes here }
ここで、デュアルコア CPU を使用している場合、なぜ 4 つのワーカー プロセスが作成されるのかという質問があります。
これは、論理コアの数が 4 であるためです。私の CPU はハイパースレッディングまたは同時マルチスレッド (SMT) をサポートしています。
レストランでは、調理には時間がかかるため、ウェイターが注文を受け取り、その注文を調理チームに伝えます。テーブルの清掃やその他のウェイター関連の仕事が来たら、ウェイターがこれを行います。注文の準備ができたら、調理人はウェイターに料理を返し、ウェイターはその料理を顧客に提供します。
これは、ワーカー スレッドに関連する同じシナリオです。大規模なデータ処理、複雑な計算、重いアルゴリズムなどの計算量の多いタスクが発生した場合、メインスレッドはこのタスクをワーカー スレッドに委任します。メインスレッドではなく、ワーカーがこのタスクを実行します。
*これは役に立ちますか? *
Node JS イベント ループはシングルスレッドであることがわかっており、この重い計算作業がメイン スレッドによって行われる場合、イベント ループはブロックされます。これらのワーカー スレッドを使用する場合、これらの重いタスクはワーカー スレッドに与えられ、メイン スレッドではなくワーカー スレッドがこれらのタスクを実行するため、イベント ループがブロックされません。
ワーカー スレッドはメッセージ パッシング システムを介してメイン スレッドと通信でき、構造化クローン (ディープ コピー) を使用してスレッド間でデータを送信できます。
ここで、ワーカー スレッドの動作を模倣しようとしています。
main.js (メインスレッド)
Master 12345 is running Worker 12346 is running Worker 12347 is running Worker 12348 is running Worker 12349 is running
worker.js (ワーカー スレッド)
const { Worker } = require('worker_threads'); function startWorker() { const worker = new Worker('./worker.js'); // Create a worker using worker.js // Listen for messages from the worker worker.on('message', (message) => { console.log('Message from worker:', message); }); // Handle errors in the worker worker.on('error', (error) => { console.error('Worker error:', error); }); // Handle worker exit worker.on('exit', (code) => { console.log(`Worker exited with code ${code}`); }); // Send a message to the worker worker.postMessage({ num: 100 }); } startWorker();
データに大きな構造が含まれている場合、データは深く複製されて渡されるため、パフォーマンスのオーバーヘッドが発生する可能性があります。
コードの動作
Worker クラスは、新しいスレッドを生成するために使用されます。
worker.postMessage を使用してワーカーにデータを送信し、worker.on('message', callback) でメッセージをリッスンできます。
ワーカー スレッドでは、parentPort がメイン スレッドと通信するためのプライマリ インターフェイスです。
メイン スレッド (parentPort.on('message')) からのメッセージをリッスンし、parentPort.postMessage を使用してメッセージを送り返すことができます。
出力は次のようになります:
const cluster = require('cluster');
さて、あなたにも質問が 1 つあります。何百ものワーカー スレッドを作成したらどうでしょうか?
しかし、その理由は、コアの数より多くのスレッドを作成すると、スレッドが CPU 時間をめぐって競合し、コンテキストの切り替えにつながり、コストが高くなり、全体的なパフォーマンスが低下するためです。
Node.js でクラスタリング、ワーカー スレッド、またはその両方を使用する必要があるのはどのような場合ですか?
1.ワーカー スレッドをいつ使用するか?
タスクには、画像/ビデオ処理、データ圧縮または暗号化、機械学習推論、科学計算などの大量の計算が含まれます
スレッド間でデータを重複せずに効率的に共有する必要があります。
アプリケーションが 1 つのプロセス内でのみ拡張する必要があるが、それでも CPU を集中的に使用するタスクの並列処理が必要な場合。
2.クラスタリングをいつ使用するか?
タスクには、Web、サーバー、チャット アプリケーション、API などの多数のクライアント リクエストの処理が含まれます。クラスタリングは、リクエストをすべての CPU コアに分散することで水平方向に拡張するのに役立ちます。
アプリケーションはプロセス間で大量のデータを共有する必要はありません。
複数の Node.js プロセスを生成して、利用可能なすべてのコアを利用したいと考えています。
3.クラスタリング スレッドとワーカー スレッドの両方を使用する場合は?
アプリケーションは HTTP リクエストを処理しますが、計算負荷の高いタスクをオフロードします。例: Web サーバーはファイルのアップロードを処理し、画像のサイズ変更やビデオのトランスコーディングを実行します。
高スループットを実現するには、プロセスレベルとスレッドレベルの両方の並列処理が必要です。 E コマース サイトでは、クラスタリングにより、複数のプロセスが受信リクエストを処理できるようになります。ワーカー スレッドは、パーソナライズされた推奨事項の生成などのバックグラウンド タスクを処理します。
ありがとうございます。
お気軽にご質問やご提案をお寄せください。
これが有益であると感じた場合は、気に入ってください。
以上がクラスタリングとワーカー スレッド - Node JSの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。