Reference
- Celery 官方文档
- 任务调度利器:Celery(廖雪峰)
Celery 简介
引用官方的一段介绍
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 .Celery is Open Source and licensed under the BSD License.
大概意思就是Celery 是一个专注于实时处理的任务队列和任务调度的系统。而且 celery 使用起来十分简单、灵活,并且可应用于分布式系统当中。
我们在现实工作中可能会碰到这么两种情况:在一次 web 请求中我们需要处理一个十分耗时的任务;在我们系统中需要定时处理一些任务。这两种都是 celery 能解决的主要问题。
Celery 应用
Application 应用
在使用 Celery 之前,我们需要先实例化 Celery. 我们可以称之为Application。
首先安装 Celery:
sudo pip install celery
Celery 默认使用 RabbitMQ 作为 broker, 所以我们可以安装一个RabbitMQ。
而后我们可以实例化 Celery
from celery import Celery
app = Celery()
而后我们便可以通过 app 来调用 Celery 的库。我们可以在实例化的时候加入更多的参数,用来定制这个 app, celery 是线程安全的,所以你可以在一个进程中使用多个 Celery 实例。
Task 任务
Task 是 Celery 应用的基石,我们所有要执行的任务都需要被修饰为一个 task,一个 task 会同时扮演 worker 和 beat 两个角色,worker 用来执行任务,beat 用来触发任务。
处理实时任务队列
现在设定我们有一个非常耗时的任务:
# tasks.py
def send_email(name):
print("准备发送邮件.")
time.sleep(5)
print("发送邮件给了{name}".format(name=name))
一般我们同步的系统中这么调用:
send_email("李琼羽")
那么我们的程序会在这里堵塞5s。
我们可以使用 Celery:
# tasks.py
import time
from celery import Celery
app = Celery()
@app.task
def send_email(name):
print("准备发送邮件.")
time.sleep(5)
print("发送邮件给了{name}".format(name=name))
然后启动 Celery 的任务处理进程:
celery -A tasks worker -l info
tasks 为模块, worker 指示为启动消费者 -l info 表示 log, 实际使用中可以用 supervisor 来管理。
然后我们来用 Celery 的方式调用:
from tasks import send_email
send_email.delay("李琼羽")
处理定时任务
在我们自己的业务系统中有一个每月15号给所以可以发送一条短信的任务,又或者我们需要每5分钟跑一次报表 sql,对于这种需求,Celery 也能很好的处理。
使用过 crontab 对此应该会很熟悉
# tasks.py
from celery import Celery
from celery.schedules import crontab
app = Celery()
@app.task
def hello(word):
print("发送时间是: {word}".format(word=word))
@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
# Calls test('hello') every 10 seconds.
sender.add_periodic_task(10.0, cc.s('每10秒一次'))
# Executes every Monday morning at 7:30 a.m.
sender.add_periodic_task(
crontab(minute='*/1', ),
cc.s('每分钟一次'),
)
sender.add_periodic_task(
crontab(minute=30, hour=12, day_of_month=15),
cc.s('每月15日12点30分发送')
)
首先我们定义了需要执行的任务,然后定义了setup_periodic_tasks ,其中* add_periodic_task *为添加任务计划,其中还支持 crontab 语法。
crontab 语法可以参考:
# 每分钟执行一次
c1 = crontab()
# 每天凌晨十二点执行
c2 = crontab(minute=0, hour=0)
# 每十五分钟执行一次
crontab(minute='*/15')
# 每周日的每一分钟执行一次
crontab(minute='*',hour='*', day_of_week='sun')
# 每周三,五的三点,七点和二十二点没十分钟执行一次
crontab(minute='*/10',hour='3,17,22', day_of_week='thu,fri')
然后我们启动 Celery 的 beat,这相当于一个生产者.
celery -A tasks beat -l info
再启动一个消费者:
celery -A tasks worker -l info
而后就能在 worker 客户端看到记录了。
在 Django 中使用 Celery
在 Django 中使用 celery 也是很方便的。为了在 Django 中使用 Celery 我们需要在项目中先实例化 Celery Application。
我们的 Django 项目:
- example/
- manage.py
- example/
- __init__.py
- settings.py
- urls.py
我们在项目下创建 celery.py :
# example/example/celery.py
import os
from celery import Celery
import logging
# 设置 django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'example.settings')
# 用项目名称实例化 Celery
app = Celery('example')
# 从 Django 配置中读取 Celery 配置
app.config_from_object('django.conf:settings', namespace='CELERY')
# 设置自动发现任务,这样可以从 Django 的各个 app 中发现 task
app.autodiscover_tasks()
然后我们在 Django 中导入:
# example/example/__init__.py
from __future__ import absolute_import, unicode_literals
from .celery import app as celery_app
__all__ = ['celery_app']
然后我们的 Django app 会是这样:
- app1/
- tasks.py
- models.py
- app2/
- tasks.py
- models.py
注意, tasks.py 的文件名是固定的,如果不是这个 Celery 将无法找到注册的 task。
然后我们可以注册任务了:
# demoapp/tasks.py
from __future__ import absolute_import, unicode_literals
from celery import shared_task
@shared_task
def add(x, y):
return x + y
@shared_task
def mul(x, y):
return x * y
@shared_task
def xsum(numbers):
return sum(numbers)
最后, 启动消费者
celery -A example worker -l info
就可以在 Django 中使用啦