Skip to content

Instantly share code, notes, and snippets.

@mStirner
Created September 7, 2018 18:10
Show Gist options
  • Save mStirner/c835bea5b0f8a518c4a8f6348d898ada to your computer and use it in GitHub Desktop.
Save mStirner/c835bea5b0f8a518c4a8f6348d898ada to your computer and use it in GitHub Desktop.
nodejs cluster without redis, support sticky balancing / websockets
const cluster = require("cluster");
const http = require("http");
const os = require("os");
const net = require("net");
const ip = require('ip');
// create seed
const seed = (Math.random() * 0xffffffff) | 0;
/**
* Hash IP
* @type Number|seed
*/
function hashHelper(ip) {
var hash = seed;
for (var i = 0; i < ip.length; i++) {
var num = ip[i];
hash += num;
hash %= 2147483648;
hash += (hash << 10);
hash %= 2147483648;
hash ^= hash >> 6;
}
hash += hash << 3;
hash %= 2147483648;
hash ^= hash >> 11;
hash += hash << 15;
hash %= 2147483648;
return hash >>> 0;
}
// create standard http server
// can be in the cluster.isMaster else statemant (is slave/!isMaster)
var server = http.createServer(function (req, res) {
res.end("Hello from, pid: " + process.pid);
});
if (cluster.isMaster) {
// workers
let workers = [];
let tcp = net.Server({
pauseOnConnect: true
}, function balance(socket) {
var addr = ip.toBuffer(socket.remoteAddress || '127.0.0.1');
var hash = hashHelper(addr);
// feedback
console.log('balancing connection %j', addr);
// send request to worker
workers[hash % workers.length].send('sticky:balance', socket);
});
// liste for listening event
tcp.once('listening', function () {
let addr = this.address();
console.log('Cluster (master) listening on %s:%d', addr.address, addr.port);
for (var i = 0; i < os.cpus().length; i++) {
let worker = cluster.fork();
workers.push(worker);
// feedback
console.log('worker=%d spawn', worker.process.pid);
}
});
// start tcp server
tcp.listen(3000, "0.0.0.0");
} else {
process.on('message', function (msg, socket) {
if (msg !== 'sticky:balance' || !socket) {
return;
}
server._connections++;
socket.server = server;
server.emit('connection', socket);
});
}
@mStirner
Copy link
Author

mStirner commented Sep 7, 2018

Based on the sticky-session module.
Support WebSockets, socket.io, Sessions & Cookies

Why ?
Because reasons....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment