我们有一个平台(app + web app),用户可以通过WebSocket连接到服务器。
出于架构设计和安全考虑,我们希望限制每个用户使用不超过1个并发连接。
我们使用python的tornado作为websocket处理程序,并维护一个连接用户的全局列表。
这就是我们的open()
函数的样子:
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
最初,我们将拒绝给定用户的第二个传入连接。移动设备失去网络连接的问题让我们改变了我们的解决方案——在这种情况下,WebSocket连接没有启动.close()
。因此,我们决定用一个新的连接代替旧的连接。
我们目前面临的问题是客户端在多个浏览器窗口上-客户端试图重新连接,标签/窗口进入重新连接的战斗。一个连接并断开另一个,另一个重新连接并断开第一个。我们在客户端(app和web)中实现了自动重新连接,以便在连接断开时(无论出于何种原因,通常是网络条件)自动重新连接。
我们尝试了指数回退,但这似乎不是一个令人满意的解决方案。
问题(s) :
有没有人遇到过类似的问题?
是否有一个通用的设计模式来解决这个问题?
如何使用user_id + device_key/cookie作为连接键?例如:
connections = {
'1': {
'iphone': ws_connection1,
'pc': ws_connection2
},
'2': {
'ipad': ws_connection3
}
}
如果这是来自新设备的请求,如果至少有一个其他设备已连接,则必须拒绝它,如果是同一设备-重新连接
谢谢,我们最终在一个传入的新连接上断开了旧连接(这里的优先级是让用户在一个新的连接上),有一个变化:在关闭之前,我们推送一个do_not_reconnect消息,这样自动重新连接将不会启动。用户必须刷新页面/应用程序重新连接断开的连接-这样就不会观察到乒乓行为