node.jssocket.iosocket.io-redis

questions about socket.io adapters


I am currently working on a node.js-based socket.io service that makes use of the node.js cluster module to spawn several node.js processen on the same machine.

The socket.io docs say that it is required to use an adapter if multiple processes are used, so that e.g. broadcasting targets not only the clients connected to the current process, but to all connected clients of every process.

  1. Do I understand it correctly, that I am required to use such an adapter even if all processes are spawned locally (i.e. not across several servers)?
  2. The server processes need to communicate from time to time (just unidirectional, i.e. broadcast a message without the need for a response). If such an adapter is in use (e.g. socket.io-redis), can I use it to broadcast to all server processes as well? Or are the adapters only used to target connected clients?

Solution

  • This is a late answer to your question ( one year later ) ... I'm sure you've figured out by now but if anyone else just learning comes across this...

    1. You do require an adapter ( socket.io-redis ) if you want to send messages across multiple node.js processes on the same machine. There is no other way currently to manage multiple sockets across different app instances and sometimes no guarantee that the client is connecting to the same instance while using the app so the adapter manages that socket connection information for you.

    2. You can code the sockets to communicate however you would like once the adapter is in place ( assuming your libraries work well together - see my related question ).

    socket.broadcast.emit will communicate to all sockets except the sending socket

    io.sockets.emit will communicate to all sockets

    socket.emit will communicate to just that socket

    Example:

    // Server
    
    var redisPort = 6379
    var io = require('socket.io');
    var redisAdapter = require('socket.io-redis');
    
    io = io.listen( httpServer ); //the server instance ( supply your own code here )
    
    io.adapter( redisAdapter({ host: 'localhost' , port : redisPort }) );//6379
    io.on('connection', function( socket ){
        
        socket.on('client-msg', function( data ){
            var msgObject = { content : '' , status : 0 };
            if( data && data.content ){
                msgObject.content = data.content;
                msgObject.status = 1;
            }
            
            io.emit('server-response', msgObject );//send to all sockets
            socket.emit( 'server-response', msgObject );//send to this socket
            socket.broadcast.emit( 'server-response', msgObject ); //send to all other sockets but not this one
        
        });
        
        socket.on('disconnect', function( data ) { 
            //do some stuff unrelated to emitting                           
        });
    });
    

    // Client
    var socketio = io.connect( window.location.origin  , { transports : ['websocket'] } );
    
    socketio.emit("send-message" , { content : msg  });
    
    socketio.on("server-response", function( data ) {
        console.log( data.content , data.status );
    });
    

    Note: the ( sparse ) socket.io docs also mention a socket.io-emitter library can be used with the adapter... I am able to send/receive messages across multiple app instances without so... I'm not sure what it is good for to be honest.