Handling websocket connections connected to different replicas

Viewed 391

Backend is running on kubernetes which has N replicas. Frontend users(browsers) listen websocket for real-time messages.

Since Backend has N replicas, each browser connects to different one. Let's say there are users A B C, all have opened 2 tabs, A1 A2 B1 B2 C1 C2.

Backend-replica-1 may hold websocket connections of A1 B1 Backend-replica-2 may hold websocket connections of A2 B2 C1 C2

(please correct me if I'm wrong till here. But, as far as I know and have tested, this is how it works)

To broadcast a message to ALL users, I publish a notification to RabbiqMQ with the message I wanted. I am using Fanout exchange, so that Each backend replica will consume that notification. Then each server sends the message to all users(connections) that it has.

One question, is if this is the correct way of doing it or is there any better way? Would it be more sensible to have a separate server for only handling WS connections?

Now, I need a solution to detect if a user closed all tabs(left the application), and update that user in db. My initial idea was to detect that on websocket disconnect event, check if user has any active connections left. But doing that seems very complex, because user may have opened 3 tabs, each connecting to different backend server.

Anyone has a clue on how to achieve it?

1 Answers

To keep track of who is connected and who closed all tabs, you need to have one DB-like instance. All you need to do is to publish an event to that instance when someone connects or disconnects.

A simple implementation would to have a dictionary with a user identifier as key and number of session as a value.

When a user connects to a websocket, you publish a connected event that increments the number of sessions.

When a user disconnects, you publish a disconnected event that decrements the number of sessions and return the remaining number of session or just a boolean if the number is equal to 0. Then you can do whatever you need to do to clean up his session.

Note: you need to make the write operation synchronous if you will have multiple threads receiving the events. A good solution is to use a SQL database which support ACID out of the box.

If you need to more control, you can extend the solution to have a publish subscribe architecture. Where the connection is bidirectional rather than the unidirectional method above. This way, if someone connects in another tab, you can interact with the first tab and show a message or disconnect based on your needs.

Related