how does node.js clustering work? - node.js

i am trying to understand the following piece of code that is use to create miltiple servers to make use of a multi core cpu.
var cluster = require("cluster");
var http = require("http");
var numCPUs = require("os").cpus().length;
var port = parseInt(process.argv[2]);
if (cluster.isMaster) {
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on("exit", function(worker, code, signal) {
cluster.fork();
});
} else {
http.createServer(function(request, response) {
console.log("Request for: " + request.url);
response.writeHead(200);
response.end("hello world\n");
}).listen(port);
}
my question is, given every created server listens on same port, what guarantees that a request won't be served by more than one server?

In node v0.10, the OS kernel always chooses which child gets the request. In node v0.11+ and io.js v1.0.0+, manual round-robin scheduling is used (except on Windows for now). This default behavior is configurable by setting an environment variable though.

Related

using nodejs cluster in production?

i was reading nodejs cluster to run multiple instances of node appication
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
}
else {
http.createServer((req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}
is using this approach good in a production environment.
where the number of requests is more
You can rather use pm2/strongloop for managing this.Because all these modules are production ready and really easy to manage.
I personally feel pm2 is awesome to manage node processes.
Use following link to know more about pm2
http://pm2.keymetrics.io/
Yes you can use cluster for as long as you are calculating your cpu length
const numCPUs = require('os').cpus().length;
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
The cluster won't create processes more than that of the cpu length
But if clusters are not manage properly it will slow down the entire application process

multiple instances of same node.js app on AWS

Is there an option on AWS to run multiple instances of same node.js app?
I try to run multiple instances of my node.js app on my computer, and it gives me EADDRINUSE error. When I change the port number in my code, save it as new js file, then I am able to run multiple instances. But how could I set this on AWS? Does maybe AWS Elastic Beanstalk have some option to set this? I couldn't find it..
This is part of my app where I communicate with clients, that's where I change the port number:
http.createServer(function(request, response){
var path = url.parse(request.url).pathname;
if(path=="/getjson"){
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('_testcb(\''+string+'\')');
console.log(new Date() + " - response sent to client");
}
}).listen(port);
Or maybe you have some better solution for running multiple instances of an same node.js app? Note that multiple instances need to share an small database.
You may want to use node's cluster api. documentation here
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('Cluster worker ' + worker.process.pid + ' died');
cluster.fork();
});
} else {
http.createServer(function(request, response){
var path = url.parse(request.url).pathname;
if(path=="/getjson"){
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('_testcb(\''+string+'\')');
console.log(new Date() + " - response sent to client");
}
}).listen(port);
}
Have you tried amazon Load Balancing? more details can be found here. Load balancer can also manage auto scaling depending on trafic. See more documentation here.

Maximum performance for node HTTP server?

I'm running a test trying to draw maximum delivery speed from a Node HTTP server. It's a simple server.
In my test I have 50K virtual clients establishing a permanent connection with the server (I run ulimit -n 99999 before). Then, upon another event, an HTTP connection to a different port, the server sends one message to each virtual client. At the end all clients receive the corresponding message.
Sending all messages takes minutes in my tests. Are there any recommendations that would help me improve these measurements so that I can send 50K messages in seconds instead of minutes?
The server is running in a m1.medium AWS instance. The idea is to improve performance with the same platform.
Copying the server code:
var http = require("http");
var connectionResponse = [];
var connectionIndex = 0;
http.createServer(function(request, response) {
console.log("Received connection " + connectionIndex);
response.setTimeout(1200000, function() {
console.log("Socket timeout");
});
connectionResponse[connectionIndex] = response;
connectionIndex++;
}).listen(8888);
http.createServer(function(request, response) {
console.log("8887 connected - Will respond");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Triggered all responses");
response.end();
console.log("Begin notifications:" + new Date().toISOString());
for(var i = 0; i < connectionIndex; i++) {
connectionResponse[i].writeHead(200, {"Content-Type": "text/plain", "Content-Length": 4, "transfer-encoding" : ""});
connectionResponse[i].write("CAFE");
connectionResponse[i].end();
}
console.log("End notifications" + new Date().toISOString());
}).listen(8887);
Setting this http://nodejs.org/api/http.html#http_agent_maxsockets to a sufficient number
var http = require('http');
http.globalAgent.maxSockets = xxx;
var https = require('https');
https.globalAgent.maxSockets = xxx;
Using nodejs clustering module, http://nodejs.org/api/cluster.html
Now, regarding the clustering, it really depends on what you want to do. The default example can go long way before you have to tweak it. An example would be
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
// Workers can share any TCP connection
// In this case its a HTTP server
http.createServer(function(req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
}

Node.js Cluster + Express always invoke the same worker

I'm trying to use the cluster module to handle multiple http requests concurrently with Express.
With the code below I'm able to spawn multiple workers and have all of them listen on the same port. The large for loop is there to simulate heavy load on the web server.
What I'd like to see is that if a worker is busy processing one http request when a second request comes in, a different worker will get invoked and handle that second request. Instead, when I try to issue multiple requests using curl, all requests are processed sequentially by one single worker; no other workers are ever invoked even though they've been forked.
Could it be that I'm using Express incorrectly? Thanks in advance!
var cluster = require('cluster');
if (cluster.isMaster) {
var cpuCount = require('os').cpus().length;
for (var i = 0; i < cpuCount; i += 1) {
cluster.fork();
}
}
else {
var http = require('http'),
app = require('express')();
http.createServer(app).listen(31415, function () {
console.log(process.pid + " listening on 31415");
});
app.get('/', function (req, res) {
var t= 0;
for(var i=0; i < 100000000; i++){
t++;
}
res.send('done');
});
}
Try not to use built-in module ?
master.js
var cp = require('child_process');
var net = require('net');
// create tcp server listen to a port
var tcp = net.createServer();
tcp.listen(8000, function(){
// detect cpu number, and fork child process
for (var i=0;i< require('os').cpus().length; i++) {
var worker = cp.fork('child.js');
worker.send(i, tcp._handle);
}
tcp.close();
});
child.js
var express = require('express');
var app = express();
process.on('message', function(id, handle){
app.get('/',function(){
console.log(process.pid+' is listening ...');
});
app.listen(handle, function(){
console.log(process.pid + 'started');
});
});
this works fine with express 3.x

Node.js singler thread model [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
node.js on multi-core machines
Since node.js makes use of single thread model, how can node.js leverage multiple cores?
Without using multiple cores, I think the usage of CPU is not enough, am I right?
you can use the core cluster module
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
// Workers can share any TCP connection
// In this case its a HTTP server
http.createServer(function(req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
}

Resources