Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reconnecting users on WebSocket connections

We have a platform (app + web app) where users connect to the server through a WebSocket connection.

For architecture design and security reasons, we want to limit each user to use no more than 1 concurrent connection.

We use python's tornado as a websocket handler and maintain a global list of connected users.

that's how our open() function looks like:

def open():
    """connections {user_id: ws_handler}
    """
    global connections
    user_id = self.get_argument("user_id", None)
    if user_id and user_id not in connections.keys():
         connections[user_id] = self 
         # proceed
    else:
         # replace the old connection
         connections[user_id].close()
         connections[user_id] = self

Initially, we would reject the second incoming connection for a given user. A problem with mobile devices losing network connection made us change our solution - in such case no .close() is initiated for the WebSocket connection. So, we decided to replace the old connection with a new one.

The problem we are facing currently is with clients on multiple browser windows - clients try to reconnect and to tabs/windows go into sort of a reconnect battle. One connects and disconnects the other, the other reconnects and disconnects the first one. We have automatic reconnect implemented in our clients (both app and web) so that they automatically reconnect when (for whatever reason, usually network conditions) connection is dropped.

We tried playing with exponential back-off but that does not seem to be a satisfactory solution.

Question(s):

Are there any people who dealt with a similar problem?

Is there a common design pattern to tackle this problem?

like image 284
haren Avatar asked Dec 09 '25 09:12

haren


2 Answers

How about to use user_id + device_key/cookie as connection key? For example:

connections = {
    '1': {
        'iphone': ws_connection1,
        'pc': ws_connection2
    },
    '2': {
        'ipad': ws_connection3
    }
}

In case this is request from new device you have to reject it if at least one another device is connected, if it's the same device - reconnect.

like image 81
Eugene Soldatov Avatar answered Dec 11 '25 23:12

Eugene Soldatov


Thanks, we ended up disconnecting the old connection on an incoming new one (priority here being to have the user on a fresh connection), with a twist: before closing, we push a do_not_reconnect message so that automatic reconnect will not kick in. User has to refresh the page / app to reconnect on the disconnected connection anew - this way no ping-pong behaviour will be observed.

like image 20
haren Avatar answered Dec 11 '25 23:12

haren



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!