Programming | Python | ML

Primary Menu

Recently, I have been working on building a server for broadcasting messages over socket connections. The basic design I had in mind was something like this-

1. The broadcast channels would basically be Redis Pub/Sub channels, with input coming from outside of the server(either a script or another server).
2. Each socket client would define the channels it wanted to listen to, via subscribe and unsubscribe requests to the server.
3. I did not want to instantiate a new Redis client per socket connection, but rather one Redis client per channel. This way, it could be shared(for listening) among all the socket connections subscribing to it.

Given below is the code for this server. The dependencies you will have to satisfy for running it are-
1. Redis
2. Node.js
3. The following Node.js modules- socket.io, redis.
If you don’t, some Googling will get it done soon enough 😛

Lines 20-43 define the server’s behavior when a new request is made by a connected socket, to subscribe to a certain broadcast channel. A broadcast channel is nothing but a Redis client that subscribes to a given pubsub channel, with the added property of a collection of listeners. Each of these Redis clients is configured to send every message it receives on the pubsub channel, to all of its listeners. The global object global_channels maintains a mapping of channel_name to Redis client instance, so that it can be shared among listeners. Each socket client also maintains its own collection of channels it subscribes to.

On unsubscribing (lines 45-54), the socket client is removed from the Redis client’s listeners, and the Redis client is removed from the socket client’s connected channels. On disconnecting, the socket is removed from the listeners of all Redis clients it subscribes to.

Now, heres a small Node.js client that will connect to the above server, subscribe to somechannel, and unsubscribe as soon as the first message is received. You will need the socket.io-client Node module for this.

The server code in this post is pretty basic, and its only job is to showcase the functionality I intended to show. For production/serious applications, there are quite a few changes you would want to make, such as-

1. Token/user-password based authentication. This could also ensure that every client can subscribe/unsubscribe only to a given/alloted set of channels.

2. Other security measures, such as disconnecting a client thats not subscribed to any channel for a given timeout.

3. Deleting channels with no listeners.

This is my first time writing proper Javascript/Node.js code, so do let me know if I have made some mistake or there are any optimizations possible to the code above 🙂 .

EDIT 1:

You could also go with one-Redis-client-per-sever (instead of channel), it would just mean storing the relevant mappings and implementing the routing logic in the ‘message’ event for the Redis client. Would provide considerable gains in case of a high number of channels.

Excellent description over Redis pub/sub and redis connection with socket.io. I have one confusion regarding using redis that if we can do use socket.io framework for publishing and replying to messages, then why did we need redis here exactly ?