Django 使用 Celery 实现异步任务
2017-12-13 09:37
871 查看
对于网站来说,给用户一个较好的体验是很重要的事情,其中最重要的指标就是网站的浏览速度。因此服务端要从各个方面对网站性能进行优化,比如可采用CDN加载一些公共静态文件,如js和css;合并css或者js从而减少静态文件的请求等等…..还有一种方法是将一些不需要立即返回给用户,可以异步执行的任务交给后台处理,以防网络阻塞,减小响应时间。看了the5fire的博客之后我受到了启发,决定从这方面进行改进。
我采用celery实现后台异步执行的需求。对于celery,先看一下网上给的celery的定义和用途:
上面的英文还是比较好理解的,简而言之,就是一个专注于实时处理和任务调度的分布式队列。我买了一本《Python Web开发实战》,那里面也介绍了celery。说了使用celery的常见场景:Web应用。当用户触发一个动作需要较长时间来执行完成时,可以把它作为任务交给celery异步执行,执行完再返回给用户。这点和你在前端使用ajax实现异步加载有异曲同工之妙。
定时任务。假设有多台服务器,多个任务,定时任务的管理是很困难的,你要在不同电脑上写不同的crontab,而且还不好管理。Celery可以帮助我们快速在不同的机器设定不同任务。
其他可以异步执行的任务。比如发送短信,邮件,推送消息,清理/设置缓存等。这点还是比较有用的。
综上所述,第1点和第3点的用途是我考虑celery的原因。目前,考虑在Django中实现两个功能:文章阅读量的统计
发送邮件
关于文章阅读量的统计,我之前的做法就是在用户每一次访问文章的时候,都会同步执行一遍+1的函数,现在打算用异步执行的方式。下面介绍在Django中的使用方法:1、环境准备安装celery,rabbitmq,django-celery.2、启动消息中间件rabbitmq。
用它的原因是celery官方推荐的就是它,也可以用Redis等,但Redis会因为断电的原因造成数据全部丢失等问题。让其在后台运行:
3、在Django中配置(源代码)
项目代码结构
对于celery的配置,需要编写几个文件:
1、dailyblog/celery.py
本模块主要是创建了celery应用,配置来自django的settings文件。
关于config_from_object,我对于如何加载配置文件还是比较感兴趣的,于是研究了一下源码,具体可以见:“celery加载配置文件”。2、settings.py配置celery,
setup_loader目的是设定celery的加载器,源码:
3、dailyblog/init.py
4、blog/tasks.py
这里面添加了一个任务。任务可以通过delay方法执行,也可以周期性地执行。厦门叉车出租
Django会创建了几个数据库,分别为:
Crontabs Intervals Periodic tasks Tasks Workers
在views.py添加异步任务:
这里不需要赋值。下面要启动celery,我采用supervisor进程管理器来管理celery:
重新加载supervisor.conf文件,然后启动celery:
至此,通过celery异步执行任务的程序写完了。除此之外,还可以写很多的异步任务,发邮件就是非常典型的一种。
我采用celery实现后台异步执行的需求。对于celery,先看一下网上给的celery的定义和用途:
12345 | Celery is a simple, flexible, and reliable distributed system to process vast amounts of messages, while providing operations with the tools required to maintain such a system. It’s a task queue with focus on real-time processing, while also supporting task scheduling. Celery has a large and diverse community of users and contributors, you should come join us on IRC or our mailing-list. |
定时任务。假设有多台服务器,多个任务,定时任务的管理是很困难的,你要在不同电脑上写不同的crontab,而且还不好管理。Celery可以帮助我们快速在不同的机器设定不同任务。
其他可以异步执行的任务。比如发送短信,邮件,推送消息,清理/设置缓存等。这点还是比较有用的。
综上所述,第1点和第3点的用途是我考虑celery的原因。目前,考虑在Django中实现两个功能:文章阅读量的统计
发送邮件
关于文章阅读量的统计,我之前的做法就是在用户每一次访问文章的时候,都会同步执行一遍+1的函数,现在打算用异步执行的方式。下面介绍在Django中的使用方法:1、环境准备安装celery,rabbitmq,django-celery.2、启动消息中间件rabbitmq。
用它的原因是celery官方推荐的就是它,也可以用Redis等,但Redis会因为断电的原因造成数据全部丢失等问题。让其在后台运行:
1 | sudo rabbitmq-server -detached |
项目代码结构
12345678910111213141516 | dailyblog ├── blog│ ├── models.py│ ├── serializer.py│ ├── tasks.py│ ├── urls.py│ ├── views.py├── config.yaml├── dailyblog│ ├── celery.py│ ├── __init__.py│ ├── __init__.pyc│ ├── settings.py│ ├── urls.py│ ├── wsgi.py |
1 2 3 4 5 6 7 | 1、dailyblog/celery.py 2、dailyblog/settings.py 3、blog/tasks.py 4、dailyblog/__init__.py |
本模块主要是创建了celery应用,配置来自django的settings文件。
1234567891011121314 | from __future__ import absolute_import,unicode_literals #目的是拒绝隐士引入,celery.py和celery冲突。import osfrom celery import Celeryfrom django.conf import settings os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dailyblog.settings") #创建celery应用app = Celery('dailyblog')#You can pass the object directly here, but using a string is better since then the worker doesn’t have to serialize the object.app.config_from_object('django.conf:settings')#如果在工程的应用中创建了tasks.py模块,那么Celery应用就会自动去检索创建的任务。比如你添加了一个任务,在django中会实时地检索出来。app.autodiscover_tasks(lambda :settings.INSTALLED_APPS) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import djcelery djcelery.setup_loader() #末尾添加 CELERYBEAT_SCHEDULER = ‘djcelery.schedulers.DatabaseScheduler‘ # 这是使用了django-celery默认的数据库调度模型,任务执行周期都被存在你指定的orm数据库中 #INstalled_apps INSTALLED_APPS = ( ‘django.contrib.admin‘, ‘django.contrib.auth‘, ‘django.contrib.contenttypes‘, ‘django.contrib.sessions‘, ‘django.contrib.messages‘, ‘django.contrib.staticfiles‘, ‘djcelery‘, #### 这里增加了djcelery 也就是为了在django admin里面可一直接配置和查看celery ‘blog‘, ### ) |
1234 | def setup_loader(): # noqa os.environ.setdefault( b'CELERY_LOADER', b'djcelery.loaders.DjangoLoader', ) |
1 2 3 4 5 | from __future__ import absolute_import # This will make sure the app is always imported when # Django starts so that shared_task will use this app. from .celery import app as celery_app |
123456789 | from django.db.models import F from .models import Articlefrom dailyblog import celery_app @celery_app.taskdef incr_readtimes(article_id): return Article.objects.filter(id=article_id).update(read_times=F('read_times') + 1) |
这里还需要注意,如果把上面任务的返回值赋值给一个变量,那么程序也会被阻塞,需要等待异步任务返回的结果。因此,实际应用不需要赋值。
上面的代码写好后,要执行数据库更新:1 2 | python manage.py makemigrations python manage.py migrate. |
Crontabs Intervals Periodic tasks Tasks Workers
在views.py添加异步任务:
1234567 | from .tasks import incr_readtimesclass ArticleDetailView(BaseMixin,DetailView): def get(self, request, *args, **kwargs): ....... incr_readtimes.delay(self.object.id) |
1 2 3 4 5 6 7 8 9 10 | [program:celery] command= celery -A dailyblog worker --loglevel=INFO directory=/srv/dailyblog/www/ numprocess=1 startsecs=0 stopwaitsecs=0 autostart=true autorestart=true stdout_logfile=/tmp/celery.log stderr_logfile=/tmp/celery.err |
1 | supervisorctl start celery |
相关文章推荐
- Python Django Celery 实现异步任务(二)使用rabbitmq 作为broker
- 用 Flask 来写个轻博客 (26) — 使用 Flask-Celery-Helper 实现异步任务
- Django中如何使用django-celery完成异步任务2(转)
- 在tornado中使用celery实现异步任务处理之一
- Django中如何使用django-celery完成异步任务
- 使用django+celery+RabbitMQ实现异步执行
- 异步任务队列Celery在Django中的使用
- Django中如何使用django-celery完成异步任务 (1)
- 异步任务队列Celery在Django中的使用
- 异步任务利器Celery(二)在django项目中使用Celery
- jango中如何使用django-celery完成异步任务 (1)
- 在tornado中使用celery实现异步任务处理之中的一个
- 使用django+celery+RabbitMQ实现异步执行
- Django中如何使用django-celery完成异步任务 (2)
- Django中使用django-celery完成异步任务(1)
- 使用 django+celery+RabbitMQ 实现异步执行
- Django 使用celery做异步任务处理
- 使用django+celery+RabbitMQ实现异步执行
- 异步任务利器Celery(二)在django项目中使用Celery
- 使用 django+celery+RabbitMQ 实现异步执行