Skip to content

Instantly share code, notes, and snippets.

@mStirner
Created September 7, 2018 18:28
Show Gist options
  • Save mStirner/c47bc7a6f3eee318e3be26554e982901 to your computer and use it in GitHub Desktop.
Save mStirner/c47bc7a6f3eee318e3be26554e982901 to your computer and use it in GitHub Desktop.
HTTP cluster, load balancing, witout redis. Support socket.io / user logins / cookies
const net = require("net");
const ip = require('ip');
const os = require("os");
const cluster = require("cluster");
module.exports = function (seed) {
/**
* 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;
}
// 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, "127.0.0.1");
};
const http = require("http");
const fs = require("fs");
module.exports = function () {
// create standard http server
// can be in the cluster.isMaster else statemant (is slave/!isMaster)
var server = http.createServer(function (req, res) {
res.write(fs.readFileSync(__dirname + "/public/index.html", ));
res.end();
});
// FOR DEMO PURPOSE ONLY!
var io = require('socket.io')(server);
io.on('connection', function (socket) {
console.log('a user connected');
});
process.on('message', function (msg, socket) {
if (msg !== 'sticky:balance' || !socket) {
return;
}
server._connections++;
socket.server = server;
server.emit('connection', socket);
});
};
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://127.0.0.1:3000');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
</head>
<body>
socket.io demo
</body>
</html>
const cluster = require("cluster");
// create seed
const seed = (Math.random() * 0xffffffff) | 0;
if (cluster.isMaster) {
require("./http.master.js")(seed);
} else {
require("./http.worker.js")(seed);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment