Home  >  Article  >  Web Front-end  >  Let's talk about the Nodejs-cluster module and introduce how to use it.

Let's talk about the Nodejs-cluster module and introduce how to use it.

青灯夜游
青灯夜游forward
2021-12-13 18:44:022082browse

This article will take you to understand the Nodejs-cluster module in node, and introduce the usage of the Nodejs-cluster module. I hope it will be helpful to everyone!

Let's talk about the Nodejs-cluster module and introduce how to use it.

The interviewer will sometimes ask you, please tell me nodejsHow to start multi-process, the cluster module should immediately appear in your mind , now let me take you to explore the use of the cluster module.

Basic usage

Node.js runs in a single process by default. For 32-bit systems, up to 512MB of memory can be used, and for 64-bit systems, up to 1GB of memory can be used. For computers with multi-core CPUs, this is very inefficient because only one core is running and the other cores are idle. The cluster module was proposed to solve this problem.

The cluster module allows the establishment of a main process and several worker processes, with the main process monitoring and coordinating the running of the worker processes. Workers use inter-process communication to exchange messages. The cluster module has a built-in load balancer and uses the Round-robin algorithm to coordinate the load between worker processes. When running, all newly established links are completed by the main process, and then the main process assigns the TCP connection to the designated worker process.

var cluster = require('cluster');
var os = require('os');

if (cluster.isMaster){
  for (var i = 0, n = os.cpus().length; i < n; i += 1){
    cluster.fork();
  }
} else {
  http.createServer(function(req, res) {
    res.writeHead(200);
    res.end("hello world\n");
  }).listen(8000);
}

The above code first determines whether the current process is the main process (cluster.isMaster). If so, create several new worker processes according to the number of CPU cores; if not, it means that the current process is a worker process. Then start a server program in this process.

One disadvantage of the above code is that once the work process hangs, the main process cannot know. In order to solve this problem, you can deploy listening functions for online events and exit events in the main process.

var cluster = require(&#39;cluster&#39;);

if(cluster.isMaster) {
  var numWorkers = require(&#39;os&#39;).cpus().length;
  console.log(&#39;Master cluster setting up &#39; + numWorkers + &#39; workers...&#39;);

  for(var i = 0; i < numWorkers; i++) {
    cluster.fork();
  }

  cluster.on(&#39;online&#39;, function(worker) {
    console.log(&#39;Worker &#39; + worker.process.pid + &#39; is online&#39;);
  });

  cluster.on(&#39;exit&#39;, function(worker, code, signal) {
    console.log(&#39;Worker &#39; + worker.process.pid + &#39; died with code: &#39; + code + &#39;, and signal: &#39; + signal);
    console.log(&#39;Starting a new worker&#39;);
    cluster.fork();
  });
}

In the above code, once the main process listens to the exit event of the worker process, it will restart a worker process. Once the worker process is started successfully and can run normally, an online event will be emitted.

worker object

The worker object is the return value of cluster.fork() and represents a worker process.

Its properties and methods are as follows.

(1) worker.id

worker.id returns the unique process number of the current worker. This number is also the index value in cluster.workers that points to the current process.

(2) worker.process

All worker processes are generated using child_process.fork(). The object returned by child_process.fork() is saved in worker.process. Through this attribute, you can get the process object where the worker is located.

(3) worker.send()

This method is used in the main process to send information to the child process.

if (cluster.isMaster) {
  var worker = cluster.fork();
  worker.send(&#39;hi there&#39;);
} else if (cluster.isWorker) {
  process.on(&#39;message&#39;, function(msg) {
    process.send(msg);
  });
}

The function of the above code is that the worker process echoes every message sent by the main process.

In the worker process, to send messages to the main process, use process.send(message); to listen to messages sent by the main process, use the following code.

process.on(&#39;message&#39;, function(message) {
  console.log(message);
});

The message sent can be a string or a JSON object. Below is an example of sending a JSON object.

worker.send({
  type: &#39;task 1&#39;,
  from: &#39;master&#39;,
  data: {
    // the data that you want to transfer
  }
});

cluster.workers object

This object is only available to the main process and includes all worker processes. The key value of each member is a worker process object, and the key name is the worker.id attribute of the worker process.

function eachWorker(callback) {
  for (var id in cluster.workers) {
    callback(cluster.workers[id]);
  }
}
eachWorker(function(worker) {
  worker.send(&#39;big announcement to all workers&#39;);
});

The above code is used to traverse all worker processes.

The data event of the current socket can also use the id attribute to identify the worker process.

socket.on(&#39;data&#39;, function(id) {
  var worker = cluster.workers[id];
});

Cluster module attributes and methods

isMaster, isWorker

isMaster property returns a A Boolean value indicating whether the current process is the main process. This attribute is determined by process.env.NODE_UNIQUE_ID. If process.env.NODE_UNIQUE_ID is undefined, it means that the process is the main process.

The isWorker attribute returns a Boolean value indicating whether the current process is a work process. It is exactly the opposite value of the isMaster attribute.

fork()

The fork method is used to create a new worker process, and the context is copied to the main process. Only the main process can call this method.

This method returns a worker object.

kill()

The kill method is used to terminate the worker process. It can accept a parameter representing a system signal.

If it is currently the main process, it will terminate the contact with worker.process, and then send the system signal method to the worker process. If it is currently a worker process, it will terminate communication with the main process, then exit, returning 0.

In previous versions, this method was also called worker.destroy().

listening event

After the worker process calls the listening method, the "listening" event is transmitted to the server of the process and then to the main process.

The callback function of this event accepts two parameters, one is the current worker object, and the other is the address object, including URL, port, address type (IPv4, IPv6, Unix socket, UDP) and other information. This is useful for Node applications that serve multiple URLs.

Restart Node service without interruption

重启服务需要关闭后再启动,利用cluster模块,可以做到先启动一个worker进程,再把原有的所有work进程关闭。这样就能实现不中断地重启Node服务。

首先,主进程向worker进程发出重启信号。

workers[wid].send({type: &#39;shutdown&#39;, from: &#39;master&#39;});

worker进程监听message事件,一旦发现内容是shutdown,就退出。

process.on(&#39;message&#39;, function(message) {
  if(message.type === &#39;shutdown&#39;) {
    process.exit(0);
  }
});

下面是一个关闭所有worker进程的函数。

function restartWorkers() {
  var wid, workerIds = [];
  for(wid in cluster.workers) {
    workerIds.push(wid);
  }

  workerIds.forEach(function(wid) {
    cluster.workers[wid].send({
      text: &#39;shutdown&#39;,
      from: &#39;master&#39;
     });
    setTimeout(function() {
      if(cluster.workers[wid]) {
        cluster.workers[wid].kill(&#39;SIGKILL&#39;);
      }
    }, 5000);
  });
};

PM2模块

PM2模块是cluster模块的一个包装层。它的作用是尽量将cluster模块抽象掉,让用户像使用单进程一样,部署多进程Node应用。

// app.js
var http = require(&#39;http&#39;);

http.createServer(function(req, res) {
  res.writeHead(200);
  res.end("hello world");
}).listen(8080);

用PM2从命令行启动这段代码

$ pm2 start app.js -i 4

上面代码的i参数告诉PM2,这段代码应该在cluster_mode启动,且新建worker进程的数量是4个。如果i参数的值是0,那么当前机器有几个CPU内核,PM2就会启动几个worker进程。

如果一个worker进程由于某种原因挂掉了,会立刻重启该worker进程。

# 重启所有worker进程
$ pm2 reload all

每个worker进程都有一个id,可以用下面的命令查看单个worker进程的详情。

$ pm2 show <worker id>

关闭worker进程的时候,可以部署下面的代码,让worker进程监听shutdown消息。一旦收到这个消息,进行完毕收尾清理工作再关闭

process.on(&#39;message&#39;, function(msg) {
  if (msg === &#39;shutdown&#39;) {
    close_all_connections();
    delete_logs();
    server.close();
    process.exit(0);
  }
});

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

The above is the detailed content of Let's talk about the Nodejs-cluster module and introduce how to use it.. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.cn. If there is any infringement, please contact admin@php.cn delete