作者:勇胆识_156 | 来源:互联网 | 2022-12-07 11:11
我正在考虑使用django-notifications和Web Sockets向iOS/Android和Web应用程序发送实时通知.所以我可能会使用Django频道.
我可以使用Django频道实时跟踪用户的在线状态吗?如果是,那么如何在不经常轮询服务器的情况下实现这一目标?
我正在寻找最佳实践,因为我找不到任何合适的解决方案.
更新:
我到目前为止尝试的是以下方法:使用Django Channels,我实现了一个WebSocket使用者,在连接时将用户状态设置为'online'
,而当套接字断开时,用户状态将被设置为'offline'
.最初我想要包括'away'
状态,但我的方法无法提供这种信息.此外,当用户使用来自多个设备的应用程序时,我的实现将无法正常工作,因为连接可以在设备上关闭,但仍然在另一个设备上打开; 'offline'
即使用户有另一个打开的连接,状态也将设置为.
class MyConsumer(AsyncConsumer):
async def websocket_connect(self, event):
# Called when a new websocket connection is established
print("connected", event)
user = self.scope['user']
self.update_user_status(user, 'online')
async def websocket_receive(self, event):
# Called when a message is received from the websocket
# Method NOT used
print("received", event)
async def websocket_disconnect(self, event):
# Called when a websocket is disconnected
print("disconnected", event)
user = self.scope['user']
self.update_user_status(user, 'offline')
@database_sync_to_async
def update_user_status(self, user, status):
"""
Updates the user `status.
`status` can be one of the following status: 'online', 'offline' or 'away'
"""
return UserProfile.objects.filter(pk=user.pk).update(status=status)
注意:
我目前的工作解决方案是使用带有API端点的Django REST框架,让客户端应用程序发送具有当前状态的HTTP POST请求.例如,Web应用程序跟踪鼠标事件并且online
每隔X秒不断POST 状态,当没有更多鼠标事件POST away
状态时,当选项卡/窗口即将关闭时,应用程序发送具有状态的POST请求offline
.这是一个可行的解决方案,具体取决于我在发送offline
状态时遇到的问题,但是它有效.
我正在寻找的是一个更好的解决方案,不需要不断轮询服务器.
1> C14L..:
使用WebSockets绝对是更好的方法.
您可以计算连接数,而不是二进制"在线"/"离线"状态:当新的WebSocket连接时,将"在线"计数器增加1,当WebSocket断开连接时,减少它.这样,当它出现时0
,用户在所有设备上都处于脱机状态.
像这样的东西
@database_sync_to_async
def update_user_incr(self, user):
UserProfile.objects.filter(pk=user.pk).update(Online=F('online') + 1)
@database_sync_to_async
def update_user_decr(self, user):
UserProfile.objects.filter(pk=user.pk).update(Online=F('online') - 1)
2> ddiazp..:
最好的方法是使用Websockets。
但是我认为您不仅应该存储状态,还应该存储会话密钥或设备标识。如果仅使用计数器,则会丢失有价值的信息,例如,用户在特定时刻连接了什么设备。这在某些项目中很关键。此外,如果发生错误(断开连接,服务器崩溃等),您将无法跟踪与每个设备相关的计数器,并且可能最终需要重置计数器。
我建议您将此信息存储在另一个相关表中:
from django.db import models
from django.conf import settings
class ConnectionHistory(models.Model):
OnLINE= 'online'
OFFLINE = 'offline'
STATUS = (
(ONLINE, 'On-line'),
(OFFLINE, 'Off-line'),
)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
device_id = models.CharField(max_lenght=100)
status = models.CharField(
max_lenght=10, choices=STATUS,
default=ONLINE
)
first_login = models.DatetimeField(auto_now_add=True)
last_echo = models.DatetimeField(auto_now=True)
class Meta:
unique_together = (("user", "device_id"),)
这样,您就可以在每台设备上记录一条记录,以跟踪它们的状态以及其他一些信息,例如ip地址,地理等。然后,您可以执行以下操作(基于您的代码):
@database_sync_to_async
def update_user_status(self, user, device_id, status):
return ConnectionHistory.objects.get_or_create(
user=user, device_id=device_id,
).update(status=status)
如何获得设备标识
有很多库都可以这样做,例如https://www.npmjs.com/package/device-uuid。他们只是使用一堆浏览器参数来生成哈希键。它比单独使用会话ID更好,因为它的更改频率较低。
追踪离开状态
完成每个操作后,您只需进行更新即可last_echo
。通过这种方式,您可以弄清楚是谁连接了或与谁断开了连接以及与哪个设备相连。
优点:万一发生崩溃,重新启动等情况,可以随时重新建立跟踪状态。