Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I Handle Socket.IO rooms with cluster?

I have a server working with cluster and to make that work with socke.IO I am using sticky-session, but I have a problem with my rooms (I don't know if the way I did is the best option): The cluster is instantiating processes and each process has a specific number of rooms.

  • Server
    • Process 1
      • Room1
      • Room2
      • Room N
    • Process 2
      • Room1
      • Room2
      • Room N

The way I did to connect some user to the rooms (with only one process) is using the route, where the user access a page and when he tries to make a connection with Socket.io I check the URL and with that information I insert him in a room.

My problem is implementing this server with cluster I can not insert the user in specific rooms because there is some rooms that only exist in specific processes and sticky session put him in another process. How can I put an user in a room that is in another process ? Also The use can only to see the routes of the process he is in the server and I would like to show every rooms in the page.

I already has read about Redis-Adapter but I didn't find solutions on github using Socket.io + Cluster(Sticky-session + redis-adapter) + rooms.

Follow my code to share what I have done:

//Cluster.Master with simplified Code
if (cluster.isMaster) {

   var workers = [];
   // Spawn workers.
   for (var i = 0; i < num_processes; i++) {
      spawn(i);
   }

   // Create the outside facing server listening on our port.
   var server = net.createServer({
        pauseOnConnect: true
   }, function(connection) {
        // We received a connection and need to pass it to the appropriate
        // worker. Get the worker for this connection's source IP and pass
       // it the connection.
       var worker = workers[worker_index(connection.remoteAddress, num_processes)];
       worker.send('sticky-session:connection', connection);
   }).listen(process.env.PORT);
} else {
     console.log('I am worker #' + cluster.worker.id);
     var app = new express();

     //view engine
     app.set('views', './views');
     app.set('view engine', 'pug');
     //statics
     app.use(express.static(path.join(__dirname, 'public')));
     //rooms
     app.use('/', rooms);
     var server = app.listen(0, 'localhost'),
         io = sio(server);
     io.adapter(sio_redis({ host: 'localhost', port: 6379 }));

    //This File has the socket events (socket.on('messageX', function(){}))
    // And there I am 
    var realtime = require('./realtime/socketIOEvents.js')(io);

    // Listen to messages sent from the master. Ignore everything else.
    process.on('message', function(message, connection) {
    if (message !== 'sticky-session:connection') {
        return;
    }
   // Emulate a connection event on the server by emitting the
   // event with the connection the master sent us.
   server.emit('connection', connection);
   connection.resume();
});
}
like image 452
Tiago Fabre Avatar asked Oct 16 '16 19:10

Tiago Fabre


People also ask

How many rooms can Socket.IO handle?

socket.io rooms are a lightweight data structure. They are simply an array of connections that are associated with that room. You can have as many as you want (within normal memory usage limits).

How many players can Socket.IO handle?

Once you reboot your machine, you will now be able to happily go to 55k concurrent connections (per incoming IP).

How many messages per second can Socket.IO handle?

Load benchmarks Here we can see that the HTTP benchmark peaks at about~950 requests per second while Socket.io serves about ~3900 requests per second.


2 Answers

socketio-redis is a right thing to do. Every sserver/process listens to a topic in redis queue. To understand in short socketio-redis just publishes the event to every other server/process in cluster. So as far as the Rooms are concern they are just an abstraction to a group of sockets interested in listening to messages in the room.

Even if sockets are distributed to different servers/processes they can be a part of same room. As every message comes in, every server knows about it and passes on the to required sockets.

As far as correctness is concern, Your architecture is right also correct as your proxy decides also selectively forwards the message but it is increasing hops in a lifecycle of a message. You really do not need this proxy to handle socket routing.

like image 173
paparoch Avatar answered Oct 20 '22 00:10

paparoch


Here is the example code which will worked based on the room joining with.

http://www.html5gamedevs.com/topic/12321-create-a-cluster-server-with-nodejs-and-socketio/

Let me know if you have question in this post.

like image 39
Mitul Avatar answered Oct 20 '22 00:10

Mitul