Search code examples
javascriptnode.jssocketssocket.ioforwarding

socket.io router, assign to one of multiple instances


I am trying to overcome a limitation placed on how many connections TCP protocol can have opened on a single port. So i thought of a way to create multiple instances of my server running on different ports for example:

  • instance 1 (3001) server_i1.js
  • instance 2 (3002) server_i2.js
  • instance 3 (3003) server_i3.js
  • instance 4 (3004) server_i4.js

then i could have one additional file server_route.js that would check how many connections are established on each instance and forward user to less populated instance. I tried build something using cluster but it only seems to create new processes on the same port. How it can be done to have all users connect for example to http://exmaple.com:3000 and then forward them to one of four possible ports [3001, 3002, 3003, 3004]?

current server approach:

var cluster = require('cluster');
var numCPUs = require('os').cpus().length;

if(cluster.isMaster) {
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });
} else {

    var http = require('http'),
        _io = require('socket.io'),
        server = http.createServer();

    server.listen('3000', 'example.com');

    var io = _io.listen(server);

    var connections = {},
        msg_sent = 0;

    io.on('connection', function(socket) {

        connections[socket.id] = new Date().getTime();

        socket.on('client-request', function(msg) {
            msg_sent++;
        });

        socket.on('disconnect', function() {
            delete connections[socket.id];
        });

    });

    setInterval(function() {
        console.log( 'Active connections: ', Object.keys(connections).length, 'Messages sent: ', msg_sent );
    }, 1000);

}

Solution

  • Maybe use round robin? A sample implementation would look like this:

     const ports = ["3001"," 3002", "3003"];
     var current = 0;
    
    io.on('connection', function(socket) {
      socket.emit("redirect",ports[current]);
      current = (current + 1) % ports.length;
    });
    

    On clientside one would do

    (function start(port){
      const socket = io("http://localhost:"+port);
      socket.on("redirect", port => (socket.close(), start(port)));
      //whatever
    })(3000);