I. Preface
As you know, Nodejs is a single-process single-threaded server engine that can only be computed with a single CPU, no matter how powerful the hardware. So, someone developed a third-party cluster that allows node to take advantage of multi-core CPUs for parallelism.
With the development of Nodejs, let Nodejs on the production environment, it is necessary to support multi-process multi-core processing! In the V0.6.0 version, the Nodejs has built-in cluster features. Since then, Nodejs finally can be used as an independent application development solutions, reflected in the eyes of everyone.
The simplest example:
varCluster = require (' cluster '));varHTTP = require (' http ');varNumcpus = require (' OS '). CPUs (). length;if(cluster.ismaster) {Console.log ("Master start ..."); //Fork workers. for(vari = 0; i < Numcpus; i++) {cluster.fork (); } cluster.on (' Listening ',function(worker,address) {Console.log (' Listening:worker ' + worker.process.pid + ', Address: ' +address.address+ ': ' +address.port); }); Cluster.on (' Exit ',function(worker, Code, signal) {Console.log (' Worker ' + worker.process.pid + ' died '); });} Else{http.createserver (function(req, res) {Res.writehead (200); Res.end ("Hello world\n"); }). Listen (0);}
two. How the cluster works
Each worker process implements communication with the master process by using the Child_process.fork () function, based on the IPC (inter-process communication, interprocess communication).
When the worker uses Server.listen (... ) function, the parameter sequence is passed to the master process. If the master process already matches workers, the handle is passed to the worker. If Master does not match a good worker, a worker is created, and then passed and the handle is passed to the worker.
In the boundary condition, there are 3 interesting behaviors:
Note: Below Server.listen (), is on the underlying "HTTP." Server-->net. The call to the Server class.
- 1. Server.listen ({fd:7}): In the master and worker communication process, by passing the file, master listens for "file description is 7" Instead of passing a "file description of 7" reference.
- 2. Server.listen (handle): Master and Worker communication process, communication via handle function without process contact
- 3. Server.listen (0): In the master and Worker communication process, the worker in the cluster opens a random port to be shared, through the socket communication, as in the above example 57132
The load balancing of the operating system is very efficient when multiple processes are in the same resource as the accept (). node. js does not have routing logic and there is no shared state between workers. Therefore, the program should be designed to be simple, such as memory-based session.
Because workers are run on their own, they can be removed or restarted independently, depending on the needs of the program, and workers do not affect each other. As long as there is workers alive, Master will continue to receive the connection. Node does not automatically maintain the number of workers. We can build our own pool of connections.
three. Cluster's API
Website address: Http://nodejs.org/api/cluster.html#cluster_cluster
Cluster object
Various properties and functions of the cluster
Cluster.setttings: Configuring cluster Parameter objects
Cluster.ismaster: Judging is not the master node
Cluster.isworker: Determine if the worker node is not
Event: ' Fork ': Listener Creation worker process event
Event: ' Online ': Listener worker Creation Success Event
Event: ' Listening ': Listener worker to master status event
Event: ' Disconnect ': Monitoring worker disconnection Event
Event: ' Exit ': Listener worker Exit event
Event: ' Setup ': Monitoring Setupmaster events
Cluster.setupmaster ([Settings]): Set cluster parameters
Cluster.fork ([env]): Create worker process
Cluster.disconnect ([callback]): Close the Worket process
Cluster.worker: Gets the current worker object
Cluster.workers: Get all the surviving worker objects in the cluster
Worker Object
Various properties and functions of the worker: can be obtained by cluster.workers, Cluster.worket.
Worker.id: Process ID Number
Worker.process:ChildProcess Object
Worker.suicide: After disconnect (), determine whether the worker committed suicide
Worker.send (message, [Sendhandle]): Master sends a message to the worker. Note: The worker sends a message to the Send master using process.send (message)
Worker.kill ([signal= ' SIGTERM ']): kills the specified worker, alias Destory ()
Worker.disconnect (): Disconnect worker, let worker commit suicide
Event: ' message ': Listen for the message event of master and worker
Event: ' Online ': Listen for the specified worker creation success event
Event: ' Listening ': Monitor master to worker status event
Event: ' Disconnect ': Monitoring worker disconnection Event
Event: ' Exit ': Listener worker Exit event
four. Master and worker communication
varCluster = require (' cluster '));varHTTP = require (' http ');varNumcpus = require (' OS '). CPUs (). length;if(cluster.ismaster) {Console.log (' [master] ' + ' Start master ... '); for(vari = 0; i < Numcpus; i++) { varWK =cluster.fork (); Wk.send (' [master] ' + ' Hi worker ' +wk.id); } cluster.on (' Fork ',function(worker) {Console.log (' [master] ' + ' fork:worker ' +worker.id); }); Cluster.on (' Online ',function(worker) {Console.log (' [master] ' + ' online:worker ' +worker.id); }); Cluster.on (' Listening ',function(worker, address) {Console.log (' [master] ' + ' listening:worker ' + worker.id + ', pid: ' + Worker.process.pid + ', Address: ' + address.address + ': ' +address.port); }); Cluster.on (' Disconnect ',function(worker) {Console.log (' [master] ' + ' disconnect:worker ' +worker.id); }); Cluster.on (' Exit ',function(worker, Code, signal) {Console.log (' [master] ' + ' exit worker ' + worker.id + ' died '); }); functionEachworker (callback) { for(varIdinchcluster.workers) {callback (Cluster.workers[id]); }} setTimeout (function() {Eachworker (function(worker) {worker.send (' [master] ' + ' send message to worker ' +worker.id); }); }, 3000); Object.keys (cluster.workers). ForEach (function(ID) {Cluster.workers[id].on (' Message ',function(msg) {Console.log (' [master] ' + ' message ' +msg); }); });} Else if(Cluster.isworker) {Console.log (' [worker] ' + ' start worker ... ' +cluster.worker.id); Process.on (' Message ',function(msg) {Console.log (' [worker] ' +msg); Process.send (' [worker] worker ' +cluster.worker.id+ ' received! '); }); Http.createserver (function(req, res) {Res.writehead ($, {"Content-type": "Text/html"}); Res.end (' Worker ' +cluster.worker.id+ ', PID: ' +process.pid); }). Listen (3000);}
Five. The basic framework of the arrangement
varCluster = require (' cluster '));varHTTP = require (' http ');varNumcpus = require (' OS '). CPUs (). length;if(cluster.ismaster) { for(vari = 0; i < Numcpus; i++) {cluster.fork (); } cluster.on (' Fork ',function(worker) {Console.log (' [Master] Create worker. PID: ' +worker.process.pid); }); Cluster.on (' Online ',function(worker) {Console.log (' [Master] Worker online. PID: ' +worker.process.pid); }); Cluster.on (' Disconnect ',function(worker) {Console.log (' [master] ' + ' disconnect:worker: ' +worker.process.pid); }); Cluster.on (' Exit ',function(worker, Code, signal) {Console.log (' [master] ' + ' exit Worker: ' + worker.process.pid + ' died '); }); functionEachworker (callback) { for(varIdinchcluster.workers) {callback (Cluster.workers[id]); } } /*//send to Child setTimeout (function () {Eachworker (function (worker) {worker.send (' [Master] ' + ' SE ND message to worker ' + worker.id); }); }, 3000); */Object.keys (cluster.workers). ForEach (function(ID) {Cluster.workers[id].on (' Message ',function(message) {if(Message.act = = = ' suicide ')) {cluster.fork (); } }); });}Else if(Cluster.isworker) {Process.on (' Message ',function(msg) {//Send to Parent //process.send (' [worker] worker ' +cluster.worker.id+ ' received! '); }); Process.on (' Uncaughtexception ',function(Err) {process.send ({act:' Suicide '}); Process.exit (1); }); Http.createserver (function(req, res) {Res.writehead ($, {' Content-type ': ' Text/plain '}); Res.end (' Handled by child, PID is ' + Process.pid + ' \ n '); //throw new Error (' throw Exception ');//test}). Listen (3000);}
Nodejs's Cluster module uses