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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With