Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does socket.io send messages across multiple servers?

The Socket.io API has the ability to send messages to all clients.

With one server and all sockets in memory, I understand how that server one can send a message to all its clients, that's pretty obvious. But what about with multiple servers using Redis to store the sockets?

If I have client a connected to server y and client b connected to server z (and a Redis box for the store) and I do socket.broadcast.emit on one server, the client on the other server will receive this message. How?

How do the clients that are actually connected to the other server get that message?

  • Is one server telling the other server to send a message to its connected client?
  • Is the server establishing its own connection to the client to send that message?
like image 975
hackerhasid Avatar asked Jul 02 '13 17:07

hackerhasid


2 Answers

Socket.io uses MemoryStore by default, so all the connected clients will be stored in memory making it impossible (well, not quiet but more on that later) to send and receive events from clients connected to a different socket.io server.

One way to make all the socket.io servers receive all the events is that all servers use redis's pub-sub. So, instead using socket.emit one can publish to redis.

redis_client = require('redis').createClient();
redis_client.publish('channelName', data);

And all the socket servers subscribe to that channel through redis and upon receiving a message emit it to clients connected to them.

redis_sub = require('redis').createClient();
redis_sub.subscribe('channelName', 'moreChannels');

redis_sub.on("message", function (channel, message) {        
    socket.emit(channel, message);
});

Complicated Stuff !! But wait, turns out you dont actually need this sort of code to achieve the goal. Socket.io has RedisStore which essentially does what the code above is supposed to do in a nicer way so that you can write Socket.io code as you would write for a single server and will still get propagated over to other socket.io server through redis.

To summarise socket.io sends messages across multiple servers by using redis as the channel instead of memory.

like image 116
az7ar Avatar answered Nov 10 '22 13:11

az7ar


There are a few ways you can do this. More info in this question. A good explanation of how pub/sub in Redis works is here, in Redis' docs. An explanation of how the paradigm works in general is here, on Wikipedia.

Quoting the Redis docs:

SUBSCRIBE, UNSUBSCRIBE and PUBLISH implement the Publish/Subscribe messaging paradigm where (citing Wikipedia) senders (publishers) are not programmed to send their messages to specific receivers (subscribers). Rather, published messages are characterized into channels, without knowledge of what (if any) subscribers there may be. Subscribers express interest in one or more channels, and only receive messages that are of interest, without knowledge of what (if any) publishers there are. This decoupling of publishers and subscribers can allow for greater scalability and a more dynamic network topology.

like image 35
Eli Avatar answered Nov 10 '22 15:11

Eli