[この投稿は 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);
}
ワーカーは新しい接続を受け入れるために競合し、負荷の最も少ないプロセスが勝つ可能性が最も高くなります。これは非常にうまく機能し、マルチコア ボックスでスループットを非常にうまくスケールアップできます。
複数のコアを扱うのに十分な負荷がある場合は、さらにいくつかのことを行う必要があります。
NginxやApacheなどの Web プロキシの背後で Node.js サービスを実行します。これは、接続スロットリング (過負荷状態でボックスを完全にダウンさせたくない場合を除く)、URL の書き換え、静的コンテンツの提供、および他のサブサービスのプロキシを実行できるものです。
ワーカー プロセスを定期的にリサイクルします。実行時間の長いプロセスでは、わずかなメモリ リークでも最終的に加算されます。
ログ収集・監視の設定
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) ...}
個々のポートのセットアップには間違いなくいくつかの利点があります (プロセス間の結合が少なくなる、より洗練された負荷分散の決定ができるなど) が、セットアップの作業が増えることは間違いなく、組み込みのクラスター モジュールのパフォーマンスは低くなります。 -ほとんどの人に有効な複雑さの代替。