目次
1. はじめに
#2. クラスター イベント
上記からわかるように、マスター プロセスは、cluster.fork() を通じてワーカー プロセスを作成します。 cluster.fork() 内部 子プロセスは child_process.fork() を通じて作成されます。つまり、マスター プロセスとワーカー プロセスは親プロセスと子プロセスであり、child_process によって作成された親子プロセスと同様に、IPC チャネルを通じて通信します。
四、如何实现端口共享
五、如何将请求分发到多个worker
六、pm2 工作原理
七、总结
ホームページ ウェブフロントエンド jsチュートリアル Node でクラスターを使用する方法を段階的に説明します。

Node でクラスターを使用する方法を段階的に説明します。

Dec 27, 2021 pm 07:15 PM
node 集まる

この記事では、Node.js のクラスターについて詳しく説明し、クラスター イベントについて説明します。皆様のお役に立てれば幸いです。

Node でクラスターを使用する方法を段階的に説明します。

1. はじめに

Node v0.8 では、クラスター モジュールが直接導入されました。マルチコア CPU 使用率の問題を解決し、プロセスの堅牢性に対処するための比較的完全な API も提供します。

cluster モジュールは、fork メソッドを呼び出して子プロセスを作成します。これは、child_process の fork と同じメソッドです。クラスター モジュールは、クラシックなマスター/スレーブ モデルを使用します。クラスターはマスターを作成し、指定した数に従って複数の子プロセスをコピーします。cluster.isMaster プロパティを使用して、現在のプロセスがマスターであるかワーカーであるかを判断できます。 (ワーカープロセス)。マスター プロセスはすべてのサブプロセスを管理します。マスター プロセスは特定のタスクの処理を担当しません。主な仕事はスケジュールと管理です。

クラスター モジュールは、ラウンドロビン アルゴリズム (ラウンドロビン アルゴリズムとも呼ばれます) を使用する組み込みの負荷分散を使用して、スレッド間の圧力を適切に処理します。ラウンドロビン スケジューリング戦略を使用する場合、マスターはすべての受信接続リクエストを accept() し、対応する TCP リクエスト処理を選択されたワーカー プロセスに送信します (このメソッドは引き続き IPC 経由で通信します)。 公式の使用例は次のとおりです。

const cluster = require('cluster');
const cpuNums = require('os').cpus().length;
const http = require('http');

if (cluster.isMaster) {
  for (let i = 0; i < cpuNums; i++){
    cluster.fork();
  }
  // 子进程退出监听
  cluster.on(&#39;exit&#39;, (worker,code,signal) => {
    console.log(&#39;worker process died,id&#39;,worker.process.pid)
  })
} else {
  // 给子进程标注进程名
  process.title = `cluster 子进程 ${process.pid}`;
  // Worker可以共享同一个 TCP 连接,这里是一个 http 服务器
  http.createServer((req, res)=> {
    res.end(`response from worker ${process.pid}`);
  }).listen(3000);
  console.log(`Worker ${process.pid} started`);
}
ログイン後にコピー

実際には、クラスタ モジュールは child_process モジュールと net モジュールの組み合わせによって適用されます。クラスタが起動すると、内部で TCP サーバーが起動されます。cluster.fork( ) 子プロセス、この TCP サーバー側ソケットのファイル記述子がワーカー プロセスに送信されます。ワーカー プロセスがcluster.fork()を介してコピーされる場合、環境変数にNODE_UNIQUE_IDが存在します。ワーカー プロセスのネットワーク ポートをリッスンするためのlisten()呼び出しがある場合、SO_REUSEADDRポートを介してファイル記述子を取得します。再利用することで、複数の子プロセスがポートを共有できるようになります。

#2. クラスター イベント

    #fork: このイベントは、ワーカー プロセスのコピー後にトリガーされます;
  • online: 作業プロセスをコピーした後、作業プロセスはメイン プロセスにオンライン メッセージをアクティブに送信します。メイン プロセスがメッセージを受信すると、イベントがトリガーされます。
  • listening:作業プロセスで呼び出されます listen() 後 (サーバー側のソケットは共有されます)、リスニング メッセージがメイン プロセスに送信され、メイン プロセスがメッセージを受信した後、イベントがトリガーされます;
  • #disconnect: メイン プロセスとワーカー プロセス このイベントは、IPC チャネルが切断されるとトリガーされます;
  • exit: このイベントは、ワーカー プロセスが終了するときにトリガーされます;
  • setup: このイベントは、cluster.setupMaster() の実行後にトリガーされます;
  • これらのイベントのほとんどは、child_process モジュールのイベントに関連しています、プロセス間メッセージ受け渡しに基づいてカプセル化されます。
  • cluster.on(&#39;fork&#39;, ()=> {
      console.log(&#39;fork 事件... &#39;);
    })
    
    cluster.on(&#39;online&#39;, ()=> {
      console.log(&#39;online 事件... &#39;);
    })
    
    cluster.on(&#39;listening&#39;, ()=> {
      console.log(&#39;listening 事件... &#39;);
    })
    
    cluster.on(&#39;disconnect&#39;, ()=> {
      console.log(&#39;disconnect 事件... &#39;);
    })
    
    cluster.on(&#39;exit&#39;, ()=> {
      console.log(&#39;exit 事件... &#39;);
    })
    
    cluster.on(&#39;setup&#39;, ()=> {
      console.log(&#39;setup 事件... &#39;);
    })
    ログイン後にコピー

3. マスターとワーカー間の通信

上記からわかるように、マスター プロセスは、cluster.fork() を通じてワーカー プロセスを作成します。 cluster.fork() 内部 子プロセスは child_process.fork() を通じて作成されます。つまり、マスター プロセスとワーカー プロセスは親プロセスと子プロセスであり、child_process によって作成された親子プロセスと同様に、IPC チャネルを通じて通信します。

IPC の正式名は Inter-Process Communication (プロセス間通信) です。プロセス間通信の目的は、さまざまなプロセスがリソースにアクセスし、相互に作業を調整できるようにすることです。 Node の IPC チャネルはパイプ テクノロジによって実装されます。具体的な実装は libuv によって提供されます。Windows では名前付きパイプによって実装されます。*nix システムは Unix ドメイン ソケットを使用します。アプリケーション層で実装されるプロセス間通信には、単純なメッセージ イベントと送信メソッドのみがあり、非常に簡単に使用できます。

親プロセスは、実際に子プロセスを作成する前に IPC チャネルを作成してリッスンし、次に実際に子プロセスを作成し、環境変数を通じて子プロセスに通知します。 (NODE_CHANNEL_FD) この IPC チャネルのファイル記述子。起動プロセス中に、子プロセスはファイル記述子に従って既存の IPC チャネルに接続し、それによって親プロセスと子プロセス間の接続が完了します。 Node でクラスターを使用する方法を段階的に説明します。

#接続が確立されると、親プロセスと子プロセスは自由に通信できるようになります。 IPC チャネルは名前付きパイプまたはドメイン ソケットを使用して作成されるため、ネットワーク ソケットと同様に動作し、双方向通信になります。違いは、実際のネットワーク層を経由せずにシステム カーネル内でプロセス間通信を完了するため、非常に効率的であることです。 Node では、IPC チャネルは Stream オブジェクトとして抽象化されており、 send が呼び出されると、データが送信され ( write と同様)、受信したメッセージはメッセージ イベントを通じてアプリケーション層にトリガーされます ( data と同様)。

master 和 worker 进程在 server 实例的创建过程中,是通过 IPC 通道进行通信的,那会不会对我们的开发造成干扰呢?比如,收到一堆其实并不需要关心的消息?答案肯定是不会?那么是怎么做到的呢?

Node 引入进程间发送句柄的功能,send 方法除了能通过 IPC 发送数据外,还能发送句柄,第二个参数为句柄,如下所示

child.send(meeage, [sendHandle])
ログイン後にコピー

句柄是一种可以用来标识资源的引用,它的内部包含了指向对象的文件描述符。例如句柄可以用来标识一个服务器端 socket 对象、一个客户端 socket 对象、一个 UDP 套接字、一个管道等。 那么句柄发送跟我们直接将服务器对象发送给子进程有没有什么差别?它是否真的将服务器对象发送给子进程?

其实 send() 方法在将消息发送到 IPC 管道前,将消息组装成两个对象,一个参数是 handle,另一个是 message,message 参数如下所示

{
  cmd: &#39;NODE_HANDLE&#39;,
  type: &#39;net.Server&#39;,
  msg: message
}
ログイン後にコピー

发送到 IPC 管道中的实际上是要发送的句柄文件描述符,其为一个整数值。这个 message 对象在写入到 IPC 管道时会通过 JSON.stringify 进行序列化,转化为字符串。子进程通过连接 IPC 通道读取父进程发送来的消息,将字符串通过 JSON.parse 解析还原为对象后,才触发 message 事件将消息体传递给应用层使用。在这个过程中,消息对象还要被进行过滤处理,message.cmd 的值如果以 NODE_ 为前缀,它将响应一个内部事件 internalMessage ,如果 message.cmd 值为 NODE_HANDLE,它将取出 message.type 值和得到的文件描述符一起还原出一个对应的对象。这个过程的示意图如下所示

Node でクラスターを使用する方法を段階的に説明します。

在 cluster 中,以 worker 进程通知 master 进程创建 server 实例为例子。worker 伪代码如下:

// woker进程
const message = {
  cmd: &#39;NODE_CLUSTER&#39;,
  type: &#39;net.Server&#39;,
  msg: message
};
process.send(message);
ログイン後にコピー

master 伪代码如下:

worker.process.on(&#39;internalMessage&#39;, fn);
ログイン後にコピー

四、如何实现端口共享

在前面的例子中,多个 woker 中创建的 server 监听了同个端口 3000,通常来说,多个进程监听同个端口,系统会报 EADDRINUSE 异常。为什么 cluster 没问题呢?

因为独立启动的进程中,TCP 服务器端 socket 套接字的文件描述符并不相同,导致监听到相同的端口时会抛出异常。但对于 send() 发送的句柄还原出来的服务而言,它们的文件描述符是相同的,所以监听相同端口不会引起异常。

这里需要注意的是,多个应用监听相同端口时,文件描述符同一时间只能被某个进程所用,换言之就是网络请求向服务器端发送时,只有一个幸运的进程能够抢到连接,也就是说只有它能为这个请求进行服务,这些进程服务是抢占式的。

五、如何将请求分发到多个worker

  • 每当 worker 进程创建 server 实例来监听请求,都会通过 IPC 通道,在 master 上进行注册。当客户端请求到达,master 会负责将请求转发给对应的 worker;
  • 具体转发给哪个 worker?这是由转发策略决定的,可以通过环境变量 NODE_CLUSTER_SCHED_POLICY 设置,也可以在 cluster.setupMaster(options) 时传入,默认的转发策略是轮询(SCHED_RR);
  • 当有客户请求到达,master 会轮询一遍 worker 列表,找到第一个空闲的 worker,然后将该请求转发给该worker;

六、pm2 工作原理

pm2 是 node 进程管理工具,可以利用它来简化很多 node 应用管理的繁琐任务,如性能监控、自动重启、负载均衡等。

pm2 自身是基于 cluster 模块进行封装的, 本节我们主要 pm2 的 Satan 进程、God Daemon 守护进程 以及两者之间的进程间远程调用 RPC。

撒旦(Satan),主要指《圣经》中的堕天使(也称堕天使撒旦),被看作与上帝的力量相对的邪恶、黑暗之源,是God 的对立面。

Node でクラスターを使用する方法を段階的に説明します。

其中 Satan.js 提供程序的退出、杀死等方法,God.js 负责维持进程的正常运行,God 进程启动后一直运行,相当于 cluster 中的 Master进程,维持 worker 进程的正常运行。

RPC(Remote Procedure Call Protocol)是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A 服务器上,想要调用 B 服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。同一机器不同进程间的方法调用也属于 rpc 的作用范畴。 执行流程如下所示

Node でクラスターを使用する方法を段階的に説明します。

每次命令行的输入都会执行一次 satan 程序,如果 God 进程不在运行,首先需要启动 God 进程。然后根据指令,Satan 通过 rpc 调用 God 中对应的方法执行相应的逻辑。

pm2 start app.js -i 4 为例,God 在初次执行时会配置 cluster,同时监听 cluster 中的事件:

// 配置cluster
cluster.setupMaster({
  exec : path.resolve(path.dirname(module.filename), &#39;ProcessContainer.js&#39;)
});

// 监听cluster事件
(function initEngine() {
  cluster.on(&#39;online&#39;, function(clu) {
    // worker进程在执行
    God.clusters_db[clu.pm_id].status = &#39;online&#39;;
  });
  
  // 命令行中 kill pid 会触发exit事件,process.kill不会触发exit
  cluster.on(&#39;exit&#39;, function(clu, code, signal) {
    // 重启进程 如果重启次数过于频繁直接标注为stopped
    God.clusters_db[clu.pm_id].status = &#39;starting&#39;;
    // 逻辑
    // ...
  });
})();
ログイン後にコピー

在 God 启动后, 会建立 Satan 和 God 的rpc链接,然后调用 prepare 方法,prepare 方法会调用 cluster.fork 来完成集群的启动

God.prepare = function(opts, cb) {
  // ...
  return execute(opts, cb);
};

function execute(env, cb) {
  // ...
  var clu = cluster.fork(env);
  // ...
  God.clusters_db[id] = clu;
  
  clu.once(&#39;online&#39;, function() {
    God.clusters_db[id].status = &#39;online&#39;;
    if (cb) return cb(null, clu);
    return true;
  });
  return clu;
}
ログイン後にコピー

七、总结

本文从 cluster 的基本使用、事件,到 cluster 的基本实现原理,再到  pm2 如何基于 cluster 进行进程管理,带你从入门到深入原理以及了解其高阶应用,希望对你有帮助。

更多node相关知识,请访问:nodejs 教程!!

以上がNode でクラスターを使用する方法を段階的に説明します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

nvmでノードを削除する方法 nvmでノードを削除する方法 Dec 29, 2022 am 10:07 AM

nvm でノードを削除する方法: 1. 「nvm-setup.zip」をダウンロードして C ドライブにインストールします; 2. 「nvm -v」コマンドで環境変数を構成し、バージョン番号を確認します; 3. 「nvm」を使用しますinstall" コマンド ノードのインストール; 4. "nvm uninstall" コマンドでインストールしたノードを削除します。

Express を使用してノード プロジェクトでファイルのアップロードを処理する方法 Express を使用してノード プロジェクトでファイルのアップロードを処理する方法 Mar 28, 2023 pm 07:28 PM

ファイルのアップロードをどのように処理するか?次の記事では、Express を使用してノード プロジェクトでファイルのアップロードを処理する方法を紹介します。

Nodeのプロセス管理ツール「pm2」を徹底分析 Nodeのプロセス管理ツール「pm2」を徹底分析 Apr 03, 2023 pm 06:02 PM

この記事では、Node のプロセス管理ツール「pm2」について説明し、pm2 が必要な理由、pm2 のインストール方法と使用方法について説明します。皆様のお役に立てれば幸いです。

PIノードティーチング:PIノードとは何ですか? PIノードをインストールしてセットアップする方法は? PIノードティーチング:PIノードとは何ですか? PIノードをインストールしてセットアップする方法は? Mar 05, 2025 pm 05:57 PM

ピン張りのノードの詳細な説明とインストールガイドこの記事では、ピネットワークのエコシステムを詳細に紹介します - PIノードは、ピン系生態系における重要な役割であり、設置と構成の完全な手順を提供します。 Pinetworkブロックチェーンテストネットワークの発売後、PIノードは多くの先駆者の重要な部分になり、テストに積極的に参加し、今後のメインネットワークリリースの準備をしています。まだピン張りのものがわからない場合は、ピコインとは何かを参照してください。リストの価格はいくらですか? PIの使用、マイニング、セキュリティ分析。パインワークとは何ですか?ピン競技プロジェクトは2019年に開始され、独占的な暗号通貨PIコインを所有しています。このプロジェクトは、誰もが参加できるものを作成することを目指しています

ノードが Proxmox VE から完全に退避し、クラスターに再参加します ノードが Proxmox VE から完全に退避し、クラスターに再参加します Feb 21, 2024 pm 12:40 PM

ノードが ProxmoxVE から完全に退避し、クラスターに再参加するためのシナリオの説明。ProxmoxVE クラスター内のノードが損傷し、すぐに修復できない場合、障害のあるノードをクラスターから完全に追い出し、残留情報をクリーンアップする必要があります。そうしないと、障害ノードが使用していた IP アドレスを使用する新しいノードが正常にクラスターに参加できなくなり、同様に、クラスターから切り離された障害ノードが修復された後、クラスターとは関係ありませんが、クラスターに参加できなくなります。この単一ノードの Web 管理にアクセスできなくなり、バックグラウンドで元の ProxmoxVE クラスター内の他のノードに関する情報が表示され、非常に迷惑になります。クラスターからノードを削除します。ProxmoxVE が Ceph ハイパーコンバージド クラスターの場合、ホスト システム Debian 上のクラスター内の任意のノード (削除するノードを除く) にログインし、コマンドを実行する必要があります。

pkg を使用して Node.js プロジェクトを実行可能ファイルにパッケージ化する方法について説明します。 pkg を使用して Node.js プロジェクトを実行可能ファイルにパッケージ化する方法について説明します。 Dec 02, 2022 pm 09:06 PM

Nodejs実行可能ファイルをpkgでパッケージ化するにはどうすればよいですか?次の記事では、pkg を使用して Node プロジェクトを実行可能ファイルにパッケージ化する方法を紹介します。

npm ノード gyp が失敗した場合の対処方法 npm ノード gyp が失敗した場合の対処方法 Dec 29, 2022 pm 02:42 PM

「node-gyp.js」が「Node.js」のバージョンと一致しないため、npm node gyp が失敗します。解決策は次のとおりです: 1. 「npm cache clean -f」を使用してノード キャッシュをクリアします; 2. 「npm install -」を使用します。 g n" n モジュールをインストールします。 3. 「n v12.21.0」コマンドを使用して、「node v12.21.0」バージョンをインストールします。

Angular と Node を使用したトークンベースの認証 Angular と Node を使用したトークンベースの認証 Sep 01, 2023 pm 02:01 PM

認証は、Web アプリケーションの最も重要な部分の 1 つです。このチュートリアルでは、トークンベースの認証システムと、それが従来のログイン システムとどのように異なるかについて説明します。このチュートリアルを終えると、Angular と Node.js で書かれた完全に動作するデモが表示されます。従来の認証システム トークンベースの認証システムに進む前に、従来の認証システムを見てみましょう。ユーザーはログイン フォームにユーザー名とパスワードを入力し、[ログイン] をクリックします。リクエストを行った後、データベースにクエリを実行してバックエンドでユーザーを認証します。リクエストが有効な場合、データベースから取得したユーザー情報を使用してセッションが作成され、セッション情報が応答ヘッダーで返され、セッション ID がブラウザに保存されます。対象となるアプリケーションへのアクセスを提供します。

See all articles