I'm learning how to scale servers in a little sandbox I've setup. Here's the very simple code:
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const instanceId = parseInt(Math.random() * 1000);
//Allow all requests from all domains & localhost
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "POST, GET");
next();
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.get('/', function(req, res) {
console.log(`[${new Date()}] ${req.method} ${req.originalUrl} from ${req.ip} at ${instanceId}`);
res.send(`received at ${Date.now()} from ${instanceId}`);
});
app.listen(6069);
Nothing crazy, just spits out the date and the instance the request was received at.
The pm2 docs for scaling a nodejs server advised me to run:
pm2 start server.js -i 5
which worked perfectly fine. Here's an example output when I stress tested it using npm module loadtest:
server-0 [Sun Aug 07 2016 00:13:53 GMT-0400 (EDT)] GET / from ::ffff:127.0.0.1 at 847
server-1 [Sun Aug 07 2016 00:13:53 GMT-0400 (EDT)] GET / from ::ffff:127.0.0.1 at 261
server-3 [Sun Aug 07 2016 00:13:53 GMT-0400 (EDT)] GET / from ::ffff:127.0.0.1 at 328
server-2 [Sun Aug 07 2016 00:13:53 GMT-0400 (EDT)] GET / from ::ffff:127.0.0.1 at 163
server-4 [Sun Aug 07 2016 00:13:53 GMT-0400 (EDT)] GET / from ::ffff:127.0.0.1 at 351
server-0 [Sun Aug 07 2016 00:13:53 GMT-0400 (EDT)] GET / from ::ffff:127.0.0.1 at 847
server-3 [Sun Aug 07 2016 00:13:53 GMT-0400 (EDT)] GET / from ::ffff:127.0.0.1 at 328
server-1 [Sun Aug 07 2016 00:13:53 GMT-0400 (EDT)] GET / from ::ffff:127.0.0.1 at 261
server-2 [Sun Aug 07 2016 00:13:53 GMT-0400 (EDT)] GET / from ::ffff:127.0.0.1 at 163
server-4 [Sun Aug 07 2016 00:13:53 GMT-0400 (EDT)] GET / from ::ffff:127.0.0.1 at 351
server-0 [Sun Aug 07 2016 00:13:53 GMT-0400 (EDT)] GET / from ::ffff:127.0.0.1 at 847
server-3 [Sun Aug 07 2016 00:13:53 GMT-0400 (EDT)] GET / from ::ffff:127.0.0.1 at 328
Here's my question. Why didn't node throw an error that port 6069 is in use? Multiple servers are attempting to use the port—yet there's no complaining. Why?
PM2 creates it's own "embedded load-balancer which uses Round-robin algorithm to better distribute load among the workers". So it basically wraps a load-balancer around your app and proxies the request to each node it creates.
When using Round-robin scheduling policy, the master accepts() all incoming connections and sends the TCP handle for that particular connection to the chosen worker (via IPC).