在我的Django + postgresql网站中,我需要公开显示所有在某个时间点都在线(这是一个社交网站)。我该怎么做呢?例如,有没有办法枚举在前10分钟内点击我的nginx网络服务器的所有登录用户?这样的事情可行。我现在是初学者,正在寻找一个可行的解决方案。
目前为了实现这一目标,我将会话存储到数据库using an external library以使会话可以进行枚举。这允许我查询在某个时间点有多少独特用户在线。
但是这种方案会产生大量不必要的数据流量。因此,日志记录和修剪日志变得无效。此外pgFouine
告诉我,与会话相关的数据库调用是我网站目前最大的性能瓶颈。
有一个建议的解决方案here,但它使用数据库。
答案 0 :(得分: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并编写自定义模板标记,只有在缓存过时时才运行db查询。这会将结果缓存500秒。
{% cache 500 logged_in_users %}
{% expensive_query_db_for_logged_in_users %}
{% endcache %}
如果您希望您的用户数更实时,您可能必须绕过django的缓存框架,并直接与Redis通信。 将每个登录用户存储为具有设定时间的密钥。从Redis获取当前活动密钥的列表将比对sql数据库的等效查询便宜得多。它也可以用几行python代码实现。
答案 1 :(得分:0)
如果您正在使用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)。
答案 2 :(得分:0)
目前,我正在尝试不同的方法。我编写了一个中间件,在每次请求时,用户的user_id
在全局排序集中为stored。我只有在经过身份验证后才这样做,并且我使用redis键值存储来确保一切都非常快。
解决方案尚未生效。我将在这里报告更多,并在完成后给出完整答案。在标记正确的解决方案之前,我还会考虑其他答案。