Communicating Go Applications through Redis Pub/Sub Messaging Paradigm

Mehmet Cetin
HackerNoon.com
5 min readJan 21, 2017

--

Redis Pub/Sub messaging paradigm allows applications talk to each other through subscription to channels. Subscribers declare their interest in specific channels and Redis pushes messages to all subscribed clients without knowledge of what (if any) subscribers there may be. You can read more about Publish/Subscribe pattern on wikipedia.

In our case, replicas of our application runs on different machines as a docker swarm service and we need them to talk to each other. We are handling many users who are connected to our system through websocket connections. Those connections are handled by replicas of our application running on different machines or instances.

We will use Gorilla Websocket, Redigo (Redis client) and UUID for unique ID creation. The simple application we are going to demonstrate will forward JSON messages between clients. Note that, this is a simpler version of what we run on production. For the sake of simplicity and readability, I will skip possible improvements.

We start by declaring a user struct and a store to keep track of connected users.

In case you have noticed, as our application will run a http server, we are protecting our store with Mutex. Next we define the message we are going to exchange between users.

It might be better to use a Pool connection for Redis communication but we will skip it for simplicity and initialize app as follows.

At this point, we can declare a function to create a new user and subscribe to Redis Pub/Sub channel by its unique id.

Normally we do not want to panic on pub/sub connection error. You can redial Redis or borrow another connection from the pool on error. So, I do leave it as an improvement point here. (An example unique ID that we assign here is ce6df22e-b497–4a71–81c5–2da31a5566e8.)

Now we have reached the point where we will listen to published messages and deliver them to the users.

We will be calling deliverMessages function from another goroutine not to block our application. Now its time to declare our main function.

And our handler.

WebSockets can perform cross domain communication and they are not limited by the SOP (Same Origin Policy). The default upgrader checks the Origin field of the incoming request with the Host header value to confirm they are equal before allowing the request. If you want to use the default CheckOrigin function you need to ensure that your client includes the Origin header with its request. Again for easier demonstration, we are overriding the function but you should not do it for safety purposes.

This is whole you need basically. You can check the code sniplet here.

If you have reached this point, let’s try it. I started my server and opened Chrome Developer Tools. Executing commands in the console as follows.

Our server logs those connections as,

As you can see, our first and second websocket connections created two users:

User 1 ID: 7c27943d-dd98–4bfe-829f-7bd9834f9f63

User 2 ID: ffbe9040-b424–4bdc-89a9-f8b045c878c6

Lets send message to User 1 (represented by first websocket connection) from User 2.

and our server logs,

Conclusion

The good side of this implementation is, if you are running your application in a distributed/clustered manner, you can scale it with ease. If you are using Docker Swarm (like us), Kubernetes or a similar clustering service scaling is easy and this pattern works well in a situation like ours.

Note
You should handle websocket connection closings (browser closed, etc.) and Redis connections. This is just a demo script.

If you liked this article and want to follow what I am working on nowadays, please follow me on Twitter/X @thisiscetin

Hacker Noon is how hackers start their afternoons. We’re a part of the @AMI family. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.

If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!

--

--

Mehmet Cetin
HackerNoon.com

Expert in Bootstrapping AI Solutions & Engineering Management, Europe/Asia