记录 Django 网站的在线用户快照(postgresql 后端,nginx 网络服务器)
Posted
技术标签:
【中文标题】记录 Django 网站的在线用户快照(postgresql 后端,nginx 网络服务器)【英文标题】:Logging a snapshot of online users for Django website (postgresql backend, nginx webserver) 【发布时间】:2017-04-11 04:29:44 【问题描述】:在我的 Django + postgresql 网站中,我需要公开显示某个时间点所有内容都在线(这是一个社交网站)。我该怎么做呢?例如,有没有办法枚举在前 10 分钟内访问我的 nginx 网络服务器的所有登录用户?像这样的东西可以工作。我是初学者,目前正在寻找可行的解决方案。
目前为了实现这一点,我将会话存储到数据库using an external library 以使会话可枚举。这让我可以查询在某个时间点有多少唯一用户在线。
但是这种方案会产生大量不必要的数据库流量。结果,记录和修剪日志变得无效。此外,pgFouine
向我展示了与会话相关的数据库调用是我的网站目前存在的最大性能瓶颈。
有一个建议的解决方案here,但它使用数据库。
【问题讨论】:
【参考方案1】:使用 django 的 cache framework 将 db 查询的结果保存到内存中。这样您就不需要为每个页面渲染进行昂贵的数据库查询。
from django.core.cache import cache
def count_current_users():
users = cache.get('users')
if users is None:
# last count has timed out
users = do_expensive_db_query()
cache.set('users', users, timeout=500)
return users
https://docs.djangoproject.com/en/1.10/topics/cache/#basic-usage
您还可以使用Template fragment caching 并编写一个自定义模板标签,该标签仅在缓存过时时运行数据库查询。这会将结果缓存 500 秒。
% cache 500 logged_in_users %
% expensive_query_db_for_logged_in_users %
% endcache %
如果您希望您的用户计数更加实时,您可能必须绕过 django 的缓存框架,直接与 Redis 通信。 将每个登录用户存储为具有设定生存时间的密钥。从 Redis 获取当前活动键的列表将比对 sql 数据库的等效查询便宜得多。也可以只用几行python代码来实现。
【讨论】:
【参考方案2】:如果您使用 django-user-sessions,Session model 有一个 last_activity
字段。
您可以执行以下操作:
from user_sessions import Session
from datetime import datetime, timedelta
time_threshold = datetime.now() - timedelta(minutes=10)
qs = Session.objects.filter(last_activity__gt=time_threshold)
不过,django-user-sessions
在该字段上没有数据库索引,这意味着如果您有大量用户/会话,则该查询可能会很困难并且需要很长时间。更复杂的答案可能涉及创建通过 cron 作业刷新的物化视图(如果您使用的是 postgres)。
【讨论】:
【参考方案3】:目前,我正在尝试不同的方法。我编写了一个中间件,在每个请求中,用户的user_id
是全局排序集中的stored。我只在它们经过身份验证后才这样做,并且我使用 redis 键值存储来确保一切都非常快。
解决方案尚未生效。我将在这里报告更多信息,并在完成后给出完整的答案。在标记正确的解决方案之前,我还会考虑此处给出的其他答案。
【讨论】:
以上是关于记录 Django 网站的在线用户快照(postgresql 后端,nginx 网络服务器)的主要内容,如果未能解决你的问题,请参考以下文章
利用Listener实现网站累积访问人数最大同时在线人数当前登录用户数的记录
django实战仿慕课网在线视频网站(完成了70%的功能已上传github:https://github.com/huwei86/mxonline):