source : http://blog.fens.me/nodejs-core-cluster/

Starting from scratch nodejs Series articles , How to benefit from Javascript As a server script , adopt Nodejs frame web Development .Nodejs The framework is based on V8 The engine of , It's the fastest at the moment Javascript engine .chrome The browser is based on V8, Open at the same time 20-30 All the pages are smooth .Nodejs The standard web Development framework Express, Can help us quickly build web Site , Compared with PHP More efficient development , And the learning curve is lower . Great for small websites , Personalized website , Our own Geek Website !!

About author

  • Zhang Dan (Conan), The programmer Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

Reprint please indicate the source :
http://blog.fens.me/nodejs-core-cluster/

Preface
Everybody knows nodejs Is a single process single thread server engine , No matter how powerful the hardware is , Only a single CPU Calculate . therefore , Someone developed a third party cluster, Give Way node You can use multiple cores CPU To achieve parallelism .

With nodejs The development of , Give Way nodejs On the production environment , It must support multi process and multi-core processing ! stay V0.6.0 edition ,Nodejs Built in cluster Characteristics of . Since then ,Nodejs Finally, it can be used as an independent application development solution , It's in everyone's eyes .

Catalog

  1. cluster Introduce
  2. cluster Simple use
  3. cluster How it works
  4. cluster Of API
  5. master and worker Communication for
  6. use cluster Load balancing (Load Balance) — win7 Failure
  7. use cluster Load balancing (Load Balance) — ubuntu success
  8. cluster Test of load balancing strategy

1. cluster Introduce

cluster It's a nodejs Built in modules , be used for nodejs Multicore processing .cluster modular , It can help us to simplify the development difficulty of multiprocess parallel programs , Easily build a cluster for load balancing .

2. cluster Simple use

My system environment

  • win7 64bit
  • Nodejs:v0.10.5
  • Npm:1.2.19

stay win In the environment of , We go through cluster Start multicore node Provide web service .

New project catalog :


~ D:\workspace\javascript>mkdir nodejs-cluster && cd nodejs-cluster

New file :app.js


~ vi app.js var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length; if (cluster.isMaster) {
console.log("master start..."); // Fork workers.
for (var i = 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);
}

Start at console node Program


~ D:\workspace\javascript\nodejs-cluster>node app.js master start...
listening: worker 2368, Address: 0.0.0.0:57132
listening: worker 1880, Address: 0.0.0.0:57132
listening: worker 1384, Address: 0.0.0.0:57132
listening: worker 1652, Address: 0.0.0.0:57132

master It's the master node ,worker Is the run node . And then according to CPU The number of , start-up worker. I have dual core and dual channel CPU, So it was detected as 4 nucleus , Launched the 4 individual worker.

3. cluster How it works

Every worker Process by using child_process.fork() function , be based on IPC(Inter-Process Communication, Interprocess communication ), Realization and master Interprocess communication .

When worker Use server.listen(...) Function time , Pass a sequence of parameters to master process . If master The process has been matched workers, Will pass the handle to the worker . If master Not a good match worker, So it's going to create one worker, Then pass it and the handle to worker.

In the boundary conditions , Yes 3 It's an interesting behavior :
notes : below server.listen(), It's about the bottom “http.Server-->net.Server” Class .

  • 1. server.listen({fd: 7}): stay master and worker Communication process , By passing files ,master Will listen “ The document is described as 7”, Instead of delivering “ The document is described as 7” References to .
  • 2. server.listen(handle):master and worker Communication process , adopt handle Function to communicate , Instead of process connections
  • 3. server.listen(0): stay master and worker Communication process , In the cluster worker Will open a random port sharing , adopt socket signal communication , Like in the example above 57132

When multiple processes are in progress accept() With the same resources , The load balancing of the operating system is very efficient .Node.js No routing logic ,worker There is no shared state between . therefore , The program should be simple , Like memory based session.

because workers They all run on their own , According to the needs of the program , They can be deleted or restarted independently ,worker It doesn't affect each other . As long as there is workers Survive , be master Will continue to receive connections .Node No automatic maintenance workers Number of . We can build our own connection pool .

4. cluster Of API

Official website address :http://nodejs.org/api/cluster.html#cluster_cluster

cluster object
cluster The various properties and functions of

  • cluster.setttings: Configure cluster parameter objects
  • cluster.isMaster: Judgment is not master node
  • cluster.isWorker: Judgment is not worker node
  • Event: 'fork': Monitor creation worker Process events
  • Event: 'online': monitor worker Create success Events
  • Event: 'listening': monitor worker towards master State event
  • Event: 'disconnect': monitor worker Disconnection event
  • Event: 'exit': monitor worker Exit event
  • Event: 'setup': monitor setupMaster event
  • cluster.setupMaster([settings]): Set cluster parameters
  • cluster.fork([env]): establish worker process
  • cluster.disconnect([callback]): close worket process
  • cluster.worker: Get current worker object
  • cluster.workers: Get all the surviving worker object

worker object
worker The various properties and functions of : Can pass cluster.workers, cluster.worket get .

  • worker.id: process ID Number
  • worker.process: ChildProcess object
  • worker.suicide: stay disconnect() after , Judge worker Suicide or not
  • worker.send(message, [sendHandle]): master to worker Send a message . notes :worker To send master To send a message process.send(message)
  • worker.kill([signal='SIGTERM']): Kill the designated worker, Alias destory()
  • worker.disconnect(): To break off worker Connect , Give Way worker commit suicide
  • Event: 'message': monitor master and worker Of message event
  • Event: 'online': Monitor the specified worker Create success Events
  • Event: 'listening': monitor master towards worker State event
  • Event: 'disconnect': monitor worker Disconnection event
  • Event: 'exit': monitor worker Exit event

5. master and worker Communication for

Realization cluster Of API, Give Way master and worker Mutual communication .

New file : cluster.js


~ vi cluster.js var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length; if (cluster.isMaster) {
console.log('[master] ' + "start master..."); for (var i = 0; i < numCPUs; i++) {
var wk = 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');
}); function eachWorker(callback) {
for (var id in cluster.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(200, {"content-type": "text/html"});
res.end('worker'+cluster.worker.id+',PID:'+process.pid);
}).listen(3000); }

Console log :


~ D:\workspace\javascript\nodejs-cluster>node cluster.js [master] start master...
[worker] start worker ...1
[worker] [master] hi worker1
[worker] start worker ...2
[worker] [master] hi worker2
[master] fork: worker1
[master] fork: worker2
[master] fork: worker3
[master] fork: worker4
[master] online: worker1
[master] online: worker2
[master] message [worker] worker1 received!
[master] message [worker] worker2 received!
[master] listening: worker1,pid:6068, Address:0.0.0.0:3000
[master] listening: worker2,pid:1408, Address:0.0.0.0:3000
[master] online: worker3
[worker] start worker ...3
[worker] [master] hi worker3
[master] message [worker] worker3 received!
[master] listening: worker3,pid:3428, Address:0.0.0.0:3000
[master] online: worker4
[worker] start worker ...4
[worker] [master] hi worker4
[master] message [worker] worker4 received!
[master] listening: worker4,pid:6872, Address:0.0.0.0:3000
[worker] [master] send message to worker1
[worker] [master] send message to worker2
[worker] [master] send message to worker3
[worker] [master] send message to worker4
[master] message [worker] worker1 received!
[master] message [worker] worker2 received!
[master] message [worker] worker3 received!
[master] message [worker] worker4 received!

6. use cluster Load balancing (Load Balance) -- win7 Failure

New file : server.js


~ vi server.js var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length; if (cluster.isMaster) {
console.log('[master] ' + "start master..."); for (var i = 0; i < numCPUs; i++) {
cluster.fork();
} cluster.on('listening', function (worker, address) {
console.log('[master] ' + 'listening: worker' + worker.id + ',pid:' + worker.process.pid + ', Address:' + address.address + ":" + address.port);
}); } else if (cluster.isWorker) {
console.log('[worker] ' + "start worker ..." + cluster.worker.id);
http.createServer(function (req, res) {
console.log('worker'+cluster.worker.id);
res.end('worker'+cluster.worker.id+',PID:'+process.pid);
}).listen(3000);
}

Start the server :


~ D:\workspace\javascript\nodejs-cluster>node server.js
[master] start master...
[worker] start worker ...1
[worker] start worker ...2
[master] listening: worker1,pid:1536, Address:0.0.0.0:3000
[master] listening: worker2,pid:5920, Address:0.0.0.0:3000
[worker] start worker ...3
[master] listening: worker3,pid:7156, Address:0.0.0.0:3000
[worker] start worker ...4
[master] listening: worker4,pid:2868, Address:0.0.0.0:3000
worker4
worker4
worker4
worker4
worker4
worker4
worker4
worker4

use curl Tool access


C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868

We found out cluster stay win Medium bug, Only for worker4. Switch to Linux test .

7. use cluster Load balancing (Load Balance) -- ubuntu success

Linux System environment

  • Linux: Ubuntu 12.04.2 64bit Server
  • Node: v0.11.2
  • Npm: 1.2.21

Build the project : Not much to explain


~ cd :/home/conan/nodejs/
~ mkdir nodejs-cluster && cd nodejs-cluster
~ vi server.js var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length; if (cluster.isMaster) {
console.log('[master] ' + "start master..."); for (var i = 0; i < numCPUs; i++) {
cluster.fork();
} cluster.on('listening', function (worker, address) {
console.log('[master] ' + 'listening: worker' + worker.id + ',pid:' + worker.process.pid + ', Address:' + address.address + ":" + address.port);
}); } else if (cluster.isWorker) {
console.log('[worker] ' + "start worker ..." + cluster.worker.id);
http.createServer(function (req, res) {
console.log('worker'+cluster.worker.id);
res.end('worker'+cluster.worker.id+',PID:'+process.pid);
}).listen(3000);
}

Start the server


conan@conan-deskop:~/nodejs/nodejs-cluster$ node server.js
[master] start master...
[worker] start worker ...1
[master] listening: worker1,pid:2925, Address:0.0.0.0:3000
[worker] start worker ...3
[master] listening: worker3,pid:2931, Address:0.0.0.0:3000
[worker] start worker ...4
[master] listening: worker4,pid:2932, Address:0.0.0.0:3000
[worker] start worker ...2
[master] listening: worker2,pid:2930, Address:0.0.0.0:3000
worker4
worker2
worker1
worker3
worker4
worker2
worker1

use curl Tool access


C:\Users\Administrator>curl 192.168.1.20:3000
worker4,PID:2932
C:\Users\Administrator>curl 192.168.1.20:3000
worker2,PID:2930
C:\Users\Administrator>curl 192.168.1.20:3000
worker1,PID:2925
C:\Users\Administrator>curl 192.168.1.20:3000
worker3,PID:2931
C:\Users\Administrator>curl 192.168.1.20:3000
worker4,PID:2932
C:\Users\Administrator>curl 192.168.1.20:3000
worker2,PID:2930
C:\Users\Administrator>curl 192.168.1.20:3000
worker1,PID:2925

stay Linux Environment ,cluster It works correctly !!!

8. cluster Test of load balancing strategy

We are Linux below , To complete the test , Used test software : siege

install siege

~ sudo apt-get install siege

start-up node cluster

~ node server.js > server.log

function siege Start command , Per second 50 Four concurrent requests .


~ sudo siege -c 50 http://localhost:3000 HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.01 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.01 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.02 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.02 secs: 16 bytes ==> /
HTTP/1.1 200 0.01 secs: 16 bytes ==> /
HTTP/1.1 200 0.01 secs: 16 bytes ==> /
..... ^C
Lifting the server siege... done. Transactions: 3760 hits
Availability: 100.00 %
Elapsed time: 39.66 secs
Data transferred: 0.06 MB
Response time: 0.01 secs
Transaction rate: 94.81 trans/sec
Throughput: 0.00 MB/sec
Concurrency: 1.24
Successful transactions: 3760
Failed transactions: 0
Longest transaction: 0.20
Shortest transaction: 0.00 FILE: /var/siege.log
You can disable this annoying message by editing
the .siegerc file in your home directory; change
the directive 'show-logfile' to false.

We have statistics , perform 3760 Requests , Consume 39.66 second , Processing per second 94.81 Requests .

see server.log file ,


~ ls -l
total 64
-rw-rw-r-- 1 conan conan 756 9 month 28 15:48 server.js
-rw-rw-r-- 1 conan conan 50313 9 month 28 16:26 server.log ~ tail server.log
worker4
worker1
worker2
worker4
worker1
worker2
worker4
worker3
worker2
worker1

Last , use R Language analysis :server.log


~ R > df<-read.table(file="server.log",skip=9,header=FALSE)
> summary(df)
V1
worker1:1559
worker2:1579
worker3:1570
worker4:1535

We see , The request is assigned to worker The amount of data is quite . therefore ,cluster Load balancing strategy , It should be randomly assigned .

Okay , We learned another useful skill ! utilize cluster We can build multi-core applications , Make the most of CPU Bring the performance of the industry !!

Reading Nodejs Multi core processing module cluster More articles about

  1. Reading Nodejs Multi core processing module cluste

    http://blog.fens.me/nodejs-core-cluster/ Node.js Development framework Express4.x   http://blog.fens.me/nodejs-express4 ...

  2. About Nodejs Multi process module of Cluster

    About Nodejs Multi process module of Cluster   Foregoing We all know nodejs The biggest feature is single process . Non blocking operation , And it's asynchronous event driven .Nodejs These features can solve some problems very well , For example, in server development , and ...

  3. nodejs Multicore processing

    Foreword as we all know nodejs Is a single process single thread server engine , No matter how powerful the hardware is , Only a single CPU Calculate . therefore , Someone developed a third party cluster, Give Way node You can use multiple cores CPU To achieve parallelism . With nod ...

  4. Node.js: process 、 Subprocess and cluster Multi core processing module

    1.process object process An object is a global object that deals with process related information , Unwanted require quote , And is EventEmitter Example . Get process information process Object provides a lot of information API To get the current ...

  5. nodejs Of require Modules and paths

    stay nodejs in , Module can be divided into core module and file module . The core module is compiled into binary code , When quoting, just require It can be represented by , Such as (require('net')). File module , Means js file .json writing ...

  6. Use nodejs Of net Module creation TCP The server

    Use nodejs Of net Module creation TCP The server laiqun@msn.cn Contents 1. Code implementation 2. Use telnet Connect to the server test 3. Create a TCP Of client 1. Code implementation ; ...

  7. Use nodejs Of http Module creation web The server

    Use nodejs Of http Module creation web The server laiqun@msn.cn Contents 1. web Server basics 2. Node.js Of Web The server 3. Code implementation 1. web Basic knowledge of server ...

  8. Nodejs Of http modular

    One .http The server      We know the traditional HTTP The server is powered by Aphche.Nginx.IIS And so on , however Nodejs It doesn't need to ,Nodejs Provides http modular , It can be used to build the server itself , for example : ...

  9. node.js Zero basic detailed tutorial (7.5):mongo Visualization tools webstorm plug-in unit 、nodejs Auto restart module Node Supervisor( modify nodejs After that, you don't need to start the service manually )

    Chapter vii. Suggested study time 4 Hours   Total courses 10 Chapter Learning style : Read in detail , And manually implement the relevant code Learning goals : This tutorial will teach you install Node. Set up server .express.mysql.mongodb. Write back-end business logic . ...

Random recommendation

  1. Uri Each attribute value test

    asp.net Code : Uri h_uri = new Uri("http://hovertree.com/tiku/bjaf/3ntux9r9.htm?hewenqi#hewenqipl?d ...

  2. 3.6--- Double stack sorting (CC150)

    answer , The method in the textbook is better . public static Stack<Integer> sort(Stack<Integer> s) { Stack<Integer> ...

  3. row_number() OVER(PARTITION BY) Function introduction

      OVER(PARTITION BY) Function introduction Open the window function                Oracle from 8.1.6 Start providing analysis functions , Analytic functions are used to calculate some aggregate value based on groups , The difference between it and aggregate function is : For each ...

  4. java An introduction to collection classes in

    structure collection( Interface ) List( Interface ) LinkedList( class ) ArrayList( class ) Vector( class ) Stack( class ) Set( Interface ) Map( Interface ) Hashtable( class ...

  5. memcached Study —— Common commands + be based on java Client's 3 A simple implementation ( Two )

    Common commands : memcached The principle of design is simplicity , So there are not too many commands to support ~ 1. see memcached The state of , It is mainly used to analyze the usage of memory . Optimize memory allocation, etc stats see memcached Operation status of ...

  6. BZOJ 1406: [AHOI2007] Password box ( number theory )

    (x+1)(x-1) mod N = 0, enumeration N Of >N^0.5 The divisor of is taken as x+1 perhaps x-1... ------------------------------------------------ ...

  7. solve mac Next atom Failed to install the plug-in

    activate-power-mode I was moved by the amazing editing effect of , Took time to install atom, After the package,install I found this plug-in in it , But the installation failed , As shown in the figure below : gyp info it work ...

  8. Async/Await It's so simplified JavaScript Code

    Translator press :  stay Async/Await replace Promise Of 6 Among the three reasons , We compare two different asynchronous programming methods :Async/Await and Promise, This blog will introduce Async/Await How to simplify J ...

  9. .net The difference between expression return value and equal sign assignment

    .net 7.0 Among the new features of , There is an operation that uses the return value of the body of the expression . Please look at the following code : private string _userName=""; public string UserName{ ...

  10. Hive Common configuration

    1. To configure hive stay HDFS Root location on <property> <name>hive.metastore.warehouse.dir</name> <valu ...