使用 celery 为 Django 应用程序异步执行任务
Posted
技术标签:
【中文标题】使用 celery 为 Django 应用程序异步执行任务【英文标题】:Using celery to asynchronously perform a task for a Django app 【发布时间】:2016-09-23 11:46:55 【问题描述】:在我维护的一个 Django 应用程序中,用户登录并相互交换消息,论坛风格。在任何给定时间点,我都会通过检查在过去 5 分钟内记录session
对象的人来显示谁在线。为此,我使用了 Django 插件 user_sessions,它允许像常规 ORM 一样操作会话。
我的代码是这样的:
class WhoseOnlineView(ListView):
model = Session
template_name = "whose_online.html"
def get_queryset(self):
unique_user_sessions = Session.objects.filter(last_activity__gte=(timezone.now()-timedelta(minutes=5))).only('user').distinct('user')
users = [session.user for session in unique_user_sessions]
users = [user for user in users if user is not None] #sanitizing None values
return users
该网站的用户(和功能)已显着增长,并且根据 newrelic 的说法,在我所有的视图中,这个特定视图消耗的时间最多。
我想我应该将整个任务移到异步完成。我在我的生产服务器上启动并运行了 celery(使用 redis 作为消息代理)。
这可能是一项周期性任务,每 60 秒执行一次。但似乎要让它工作,我需要在数据库(或缓存)中保存结果,以便用户可以看到保存的结果,直到下一次处理其在线列表.
谁能给我一个说明性的例子来说明如何做到这一点?我正在努力解决的主要问题是如何在下一个定期任务开始之前保存(或缓存)然后显示给用户的结果。
【问题讨论】:
【参考方案1】:你可以这样做:
首先,编写 celery 任务以找出已登录的用户,例如
# fooapp.tasks
@shared_task
def whoseonline():
unique_user_sessions = Session.objects.filter(last_activity__gte=(timezone.now()-timedelta(minutes=5))).only('user').distinct('user')
users = [session.user for session in unique_user_sessions users = [user for user in users if user is not None] #sanitizing None values
# save the users to the cache
cache.set('online_users', users, 70) # expiring in 70 seconds
并设置任务以运行一定的时间,例如60 秒,添加以下内容:
# settings.py
CELERYBEAT_SCHEDULE =
'whoseonline':
'task': 'fooapp.tasks.whoseonline',
'schedule': timedelta(seconds=60), # execute every 60 seconds
'args': (),
,
到您的设置。那么,在你看来,你只需要这样做
class WhoseOnlineView(ListView):
model = Session
template_name = "whose_online.html"
def get_queryset(self):
# take the values from the cache
return cache.get('online_users')
Here 更多关于缓存和here 更多关于 celery。
您还应该记住,缓存时间到期(示例中为 70 秒)应该大于您将用于 celery 任务的计划时间(示例中为 60 秒),以便视图始终有一些东西显示。
【讨论】:
嗯,我使用的缓存后端是django.core.cache.backends.locmem.LocMemCache
。似乎一切都按预期工作,除了我无法正确设置或获取缓存。有什么方法可以测试缓存是否设置正确?我试过django debug toolbar
,据此,缓存没有被调用。
你应该看看我传给你的关于缓存的链接。您可以在那里找到如何设置所有缓存机制以及如何使用它
这正是我正在使用的。确切地说,这部分:docs.djangoproject.com/en/1.9/topics/cache/… 这是一个非常严肃的设置,所以我有点难过我所缺少的。
我一直在诊断它,当我尝试 get
视图中存储的结果时,我得到了“无”。奇怪的是,tasks.py 中的get
(紧跟在set
之后)工作得非常好。奇怪。
一定要两边使用同一个key,时间足够,随时可用。以上是关于使用 celery 为 Django 应用程序异步执行任务的主要内容,如果未能解决你的问题,请参考以下文章