为Django网站记录在线用户的快照(postgresql后端,nginx webserver)

时间:2016-11-27 09:44:47

标签: python django postgresql session nginx

在我的Django + postgresql网站中,我需要公开显示所有在某个时间点都在线(这是一个社交网站)。我该怎么做呢?例如,有没有办法枚举在前10分钟内点击我的nginx网络服务器的所有登录用户?这样的事情可行。我现在是初学者,正在寻找一个可行的解决方案。

目前为了实现这一目标,我将会话存储到数据库using an external library以使会话可以进行枚举。这允许我查询在某个时间点有多少独特用户在线。

但是这种方案会产生大量不必要的数据流量。因此,日志记录和修剪日志变得无效。此外pgFouine告诉我,与会话相关的数据库调用是我网站目前最大的性能瓶颈。

有一个建议的解决方案here,但它使用数据库。

3 个答案:

答案 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键值存储来确保一切都非常快。

解决方案尚未生效。我将在这里报告更多,并在完成后给出完整答案。在标记正确的解决方案之前,我还会考虑其他答案。