667

Node.jsは面白そうに見えますが、何かが欠けているに違いありません。Node.jsは単一のプロセスとスレッドで実行するためだけに調整されていませんか?

では、マルチコア CPU とマルチ CPU サーバーに対してどのようにスケーリングするのでしょうか? 結局のところ、できるだけ高速なシングル スレッド サーバーを作成することはすべて素晴らしいことですが、負荷が高い場合は複数の CPU を使用する必要があります。同じことがアプリケーションの高速化にも当てはまります。今日では、複数の CPU を使用してタスクを並列化する方法が採用されているようです。

Node.js はこの図にどのように適合しますか? どういうわけか複数のインスタンスを配布するという考えはありますか?

4

17 に答える 17

742

[この投稿は 2012 年 9 月 2 日時点で最新のものです (上記よりも新しい)。]

Node.js は、マルチコア マシン上で確実にスケーリングします。

はい、Node.js はプロセスごとに 1 スレッドです。これは非常に慎重な設計上の決定であり、ロック セマンティクスを扱う必要がなくなります。これに同意しない場合は、マルチスレッド コードのデバッグがいかに困難であるかをまだ理解していない可能性があります。Node.js プロセス モデルと、それがこのように機能する理由 (および複数のスレッドをサポートしない理由) の詳細については、私の他の投稿を参照してください。

では、16 コア ボックスをどのように活用すればよいでしょうか?

ふたつのやり方:

  • 画像エンコーディングのような大きな負荷のかかる計算タスクの場合、Node.js は子プロセスを起動したり、追加のワーカー プロセスにメッセージを送信したりできます。この設計では、イベントの流れを管理する 1 つのスレッドと、負荷の高い計算タスクを実行し、他の 15 個の CPU を処理する N 個のプロセスがあります。
  • Web サービスのスループットをスケーリングするには、1 つのボックスで複数の Node.js サーバーをコアごとに 1 つ実行し、要求トラフィックをそれらの間で分割する必要があります。これにより、優れた CPU アフィニティが提供され、コア数にほぼ比例してスループットがスケーリングされます。

Web サービスのスループットのスケーリング

v6.0.X 以降、Node.js にはすぐに使用できるクラスター モジュールが含まれているため、1 つのポートでリッスンできる複数のノード ワーカーを簡単にセットアップできます。これは、 npmから入手できる古い Learnboost "cluster" モジュールと同じではないことに注意してください。

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  http.Server(function(req, res) { ... }).listen(8000);
}

ワーカーは新しい接続を受け入れるために競合し、負荷の最も少ないプロセスが勝つ可能性が最も高くなります。これは非常にうまく機能し、マルチコア ボックスでスループットを非常にうまくスケールアップできます。

複数のコアを扱うのに十分な負荷がある場合は、さらにいくつかのことを行う必要があります。

  1. NginxApacheなどの Web プロキシの背後で Node.js サービスを実行します。これは、接続スロットリング (過負荷状態でボックスを完全にダウンさせたくない場合を除く)、URL の書き換え、静的コンテンツの提供、および他のサブサービスのプロキシを実行できるものです。

  2. ワーカー プロセスを定期的にリサイクルします。実行時間の長いプロセスでは、わずかなメモリ リークでも最終的に加算されます。

  3. ログ収集・監視の設定


PS: 別の投稿のコメントで、Aaron と Christopher の間で議論が行われています (この記事を書いている時点では、それが一番上の投稿です)。それに関するいくつかのコメント:

  • 共有ソケット モデルは、複数のプロセスが 1 つのポートでリッスンし、競合して新しい接続を受け入れられるようにするのに非常に便利です。概念的には、プリフォークされた Apache がこれを行うと考えることができますが、各プロセスは単一の接続のみを受け入れて終了するという重大な警告があります。Apache の効率の低下は、新しいプロセスを fork するオーバーヘッドにあり、ソケット操作とは関係ありません。
  • Node.js の場合、N 個のワーカーが単一のソケットで競合することは、非常に合理的な解決策です。別の方法は、Nginx のようなオンボックス フロントエンドをセットアップし、そのプロキシ トラフィックを個々のワーカーに設定し、新しい接続を割り当てるためにワーカーを交互に切り替えることです。2 つのソリューションのパフォーマンス特性は非常に似ています。そして、上で述べたように、Nginx (またはその代替) をとにかくノード サービスの前に置きたいと思うので、ここでの選択は実際には次のいずれかです。

共有ポート:nginx (port 80) --> Node_workers x N (sharing port 3000 w/ Cluster)

個々のポート:nginx (port 80) --> {Node_worker (port 3000), Node_worker (port 3001), Node_worker (port 3002), Node_worker (port 3003) ...}

個々のポートのセットアップには間違いなくいくつかの利点があります (プロセス間の結合が少なくなる、より洗練された負荷分散の決定ができ​​るなど) が、セットアップの作業が増えることは間違いなく、組み込みのクラスター モジュールのパフォーマンスは低くなります。 -ほとんどの人に有効な複雑さの代替。

于 2011-12-31T02:48:09.290 に答える
47

1 つの方法は、サーバー上で node.js の複数のインスタンスを実行し、それらの前にロード バランサー (できれば nginx のような非ブロッキングのもの) を配置することです。

于 2010-03-10T05:47:51.537 に答える
31

Ryan Dahl は、昨年の夏に Google で行った Tech Talkでこの質問に答えています。言い換えると、「複数のノード プロセスを実行し、それらが通信できるように適切なものを使用するだけです。たとえば、sendmsg() スタイルの IPC または従来の RPC」です。

すぐに手を汚したい場合は、spark2 Foreverモジュールをチェックしてください。これにより、複数のノード プロセスの生成が非常に簡単になります。ポート共有の設定を処理するため、それぞれが同じポートへの接続を受け入れることができます。また、プロセスが終了した場合にプロセスを再起動することを確認したい場合は、自動リスポーンも行います。

更新 - 2011 年 10 月 11 日: ノード コミュニティのコンセンサスは、マシンごとに複数のノード インスタンスを管理するための優先モジュールは クラスターになっているようです。Foreverも一見の価値があります。

于 2010-12-09T12:46:40.273 に答える
25

クラスターモジュールを使用できます。これを確認してください。

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });
} else {
    // Workers can share any TCP connection
    // In this case its a HTTP server
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end("hello world\n");
    }).listen(8000);
}
于 2014-04-27T20:23:08.653 に答える
16

Node Js は、CPU を最大限に活用するためにクラスタリングをサポートしています。クラスターで実行していない場合は、おそらくハードウェア機能を無駄にしています.

Node.js でのクラスタリングにより、同じサーバー ポートを共有できる個別のプロセスを作成できます。たとえば、ポート 3000 で 1 つの HTTP サーバーを実行する場合、それはプロセッサのシングル コアのシングル スレッドで実行される 1 つのサーバーです。

以下に示すコードを使用すると、アプリケーションをクラスター化できます。このコードはNode.jsで表現された公式コードです。

var cluster = require('cluster');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    Object.keys(cluster.workers).forEach(function(id) {
        console.log("I am running with ID : " + cluster.workers[id].process.pid);
    });

    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });
} else {

    //Do further processing.
}

完全なチュートリアルについては、この記事を確認してください

于 2015-10-02T14:53:26.630 に答える
13

マルチノードは、所有しているすべてのコアを利用します。http://github.com/kriszyp/multi-node
をご覧ください。

より単純なニーズのために、異なるポート番号でノードの複数のコピーを起動し、それらの前にロード バランサーを配置できます。

于 2010-07-20T10:04:45.197 に答える
11

クラスターモジュールを使用すると、マシンのすべてのコアを利用できます。実際、非常に一般的なプロセス マネージャーpm2を使用して、コードに手を加えることなく、わずか 2 つのコマンドでこれを利用できます。

npm i -g pm2
pm2 start app.js -i max
于 2016-11-21T22:36:12.247 に答える
8

node の将来のバージョンでは、プロセスを fork してそれにメッセージを渡すことができるようになります。Ryan は、ファイル ハンドラーも共有する方法を見つけたいと述べているため、単純な Web Worker 実装にはなりません。

現時点では、これに対する簡単な解決策はありませんが、まだ非常に早い段階であり、node は私が今まで見た中で最も急速に変化しているオープン ソース プロジェクトの 1 つです。

于 2010-03-13T18:51:05.970 に答える
7

Spark2はSparkに基づいていますが、現在は保守されていません。Clusterはその後継であり、CPUコアごとに1つのワーカープロセスを生成したり、死んだワーカーを再生成したりするなど、いくつかの優れた機能を備えています。

于 2011-03-08T13:02:49.237 に答える
7

clusterモジュールをosモジュールと組み合わせて使用​​することにより、複数のコアで node.js アプリケーションを実行できます。これは、使用している CPU の数を検出するために使用できます。

たとえばserver、バックエンドで単純な http サーバーを実行するモジュールがあり、それを複数の CPU で実行したいとします。

// Dependencies.
const server = require('./lib/server'); // This is our custom server module.
const cluster = require('cluster');
const os = require('os');

 // If we're on the master thread start the forks.
if (cluster.isMaster) {
  // Fork the process.
  for (let i = 0; i < os.cpus().length; i++) {
    cluster.fork();
  }
} else {
  // If we're not on the master thread start the server.
  server.init();
}

于 2018-09-20T12:41:34.893 に答える
5

Node workerを使用して、メイン プロセスから簡単な方法でプロセスを実行しています。正式な方法が登場するのを待っている間、うまく機能しているようです.

于 2010-05-24T17:23:40.310 に答える
5

ここでのブロックの新しい子は、LearnBoost の"Up"です。

「ゼロ ダウンタイム リロード」を提供し、さらに複数のワーカー (デフォルトでは CPU の数ですが、構成可能) を作成して、すべてのワールドの中で最高のものを提供します。

新しいですが、かなり安定しているようで、現在のプロジェクトの 1 つで楽しく使用しています。

于 2012-02-03T19:14:11.967 に答える
0

それぞれ1つのNodeJSプロセスを実行する複数のボックスの前で純粋なTCPロードバランサー(HAProxy)を使用して、NodeJSを複数のボックスにスケールアウトすることができます。

次に、すべてのインスタンス間で共有する一般的な知識がある場合は、中央のRedisストアなどを使用して、すべてのプロセスインスタンスから(たとえば、すべてのボックスから)アクセスできます。

于 2011-11-10T15:14:31.607 に答える
0

データ処理などの機能を個別のプロセスにプッシュできるように、Web サービスを UNIX ソケットをリッスンする複数のスタンドアロン サーバーとして設計することもできます。

これは、cgi プロセスがビジネス ロジックを処理し、UNIX ソケットを介してデータベースにデータをプッシュおよびプルする、ほとんどの scrpting/database Web サーバー アーキテクチャに似ています。

違いは、データ処理がポートでリッスンするノード Web サーバーとして記述されていることです。

より複雑ですが、最終的にはマルチコア開発が必要な場所です。Web リクエストごとに複数のコンポーネントを使用するマルチプロセス アーキテクチャ。

于 2010-04-12T00:39:13.363 に答える