前文:Celery中文文档:http://docs.jinkan.org/docs/celery/getting-started/first-steps-with-celery.html#first-steps
版本容易踩坑,本文版本为:
Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, 举几个实例场景中可用的例子:
Celery 在执行任务时需要通过一个消息中间件来接收和发送任务消息,以及存储任务结果, 一般使用rabbitMQ or Redis,后面会讲
Celery有一下5个核心角色
Task
就是任务,有异步任务和定时任务
Broker
中间人,接收生产者发来的消息即Task,将任务存入队列。任务的消费者是Worker。Celery本身不提供队列服务,推荐用Redis或RabbitMQ实现队列服务。
Worker
执行任务的单元,它实时监控消息队列,如果有任务就获取任务并执行它。
Beat
定时任务调度器,根据配置定时将任务发送给Broler。
Backend
用于存储任务的执行结果。
各个角色间的关系看下面这张图理解一下:
Celery有以下优点:
同时需要安装中间人broker,通常是RabbitMQ或者Redis,自行百度安装
这是redis和celery同时安装:
pip install -U "celery[redis]"
安装RabbitMQ:
sudo apt-get install rabbitmq-server
from celery import Celery
# broker是指定中间存储,backend是结果存储
app = Celery('tasks',
broker='redis://127.0.0.1/3',
backend='redis://127.0.0.1/3')
# app = Celery('tasks',broker='amqp://192.168.3.108',backend='rpc://192.168.3.108', # 新版本rpc将初步替代amqp,用的还是RabbitMQ# backend='amqp://192.168.3.108', # 如果是旧版本,没有rpc,那只能用amqp)
# 创建任务函数
@app.task
def work1():
print('这是任务1')
# 任务的发布,delay这里填函数参数
work1.delay()
启动celery,在终端启动
celery -A 任务模块名 worker -l info
在项目文件夹下创建一个python package文件夹,取名为celery_tasks,里面分别创建启动文件main.py,配置文件config.py
config.py内容,需要大写,这里的redis库不要用已经配置过的:
# 这是配置celery文件
BROKER_URL= 'redis:/127.0.0.1/0'
main文件内容
# 启动文件
from celery import Celery
# 告知celery用django的配置文件进行配置
import os
if not os.getenv('DJANGO_SETTINGS_MODULE'):
os.environ['DJANGO_SETTINGS_MODULE']= 'shanghuishop.settings.dev'
# 创建应用
app = Celery('shanghui')
# 导入celery的配置文件
# app.config_from_object('celery_tasks.config')
# 任务
app.autodiscover_tasks(['celery_tasks.email', 'celery_tasks.message'])
# celery -A celery_tasks.main worker -l info
在之前celery_tasks文件夹中创建新的文件夹email和message分别用来处理发送验证邮件和短信
这里先写发送验证email的任务,创建一个tasks.py文件在email文件夹下:
from django.core.mail import send_mail
# 在当前的tasks里面书写邮件发送任务
from celery_tasks.main import app
@app.task
def my_send(url, from_email, rec_list,html_msg):
# 传入四个参数分别是链接,发件人,收件人列表,html信息
send_mail('用户邮件激活', '点击链接激活邮箱:' + url, from_email, rec_list, html_message='点击这个激活:'+html_msg)
去对应的序列化器修改:
from celery_tasks.email.tasks import my_send
# 发送即可
my_send.delay(url, from_email, rec_list, html_msg)
还是创建一个tasks文件到message文件夹下:
from celery_tasks.main import app
from shanghuishop.libs.CCPRestSDK.sms import CCP
# 发送短信验证码
@app.task(name='send_msg')
def send_msg(msg_list):
ccp = CCP()
res = ccp.send_template_sms(
'18814886773', msg_list, 1)
print('celery短信发送结果', res)
然后是对应的views文件修改原来的功能:
from celery_tasks.message.tasks import send_msg
# 发送的具体内容,详情看之前blog
msg_list = [msg, constants.PHONE_CODE_REDIS_EXPIRES // 60]
# 发送的功能
send_msg.delay(msg_list)
flower 是一个 celery 的监控工具,它提供了一个图形用户界面,可以极大的方便我们监控任务的执行过程, 执行细节及历史记录,还提供了统计功能。
flower 安装
pip install flower
flower 使用简介,首先启动通过命令行启动 flower 进程:
flower -A proj --port=5555
还是在django项目中使用,配置内容都在config里写,注意celery版本不同需要大小写要求不同,3.1版本要大写:
# 这是配置celery文件
from datetime import timedelta
from celery.schedules import crontab
# 指定任务队列的位置
BROKER_URL = "redis://127.0.0.1/3"
# 指定消息执行结果的位置
CELERY_RESULT_BACKEND = "redis://127.0.0.1/3"
# 一定要写下面这句,指定时区,否则celery默认使用utc时间,设置的hour会延迟8小时执行
CELERY_TIMEZONE = 'Asia/Shanghai'
# 这里是四个最典型的定时任务,更多用法自行百度crontab语法
CELERYBEAT_SCHEDULE = {
# 定时任务一: 每5分钟执行一次任务(refresh1)
'refresh1': {
"task": "celery_tasks.email.tasks.refresh",
"schedule": crontab(hour='*/5'),
"args": (), # 填参数
},
# 定时任务二: 每天的凌晨2:00,执行任务(refresh2)
'refresh2': {
"task": "celery_tasks.email.tasks.refresh",
'schedule': crontab(minute=0, hour=2),
"args": ()
},
# 定时任务三:每个月的1号的6:00启动,执行任务(refresh3)
'refresh3': {
"task": "celery_tasks.email.tasks.refresh",
'schedule': crontab(hour=6, minute=0, day_of_month='1'),
"args": ()
},
# 每隔20秒启动
'sendemail every 20 seconds': {
'task': 'celery_tasks.email.tasks.send',
'schedule': timedelta(seconds=20),
'args': ()
}
}
email.tasks.py内容为:
from django.core.mail import send_mail
from django.conf import settings
# 在当前的tasks里面书写邮件发送任务
from celery_tasks.main import app
@app.task(name='my_send')
def my_send(url, from_email, rec_list, html_msg):
# 传入四个参数分别是链接,发件人,收件人列表,html信息
send_mail('用户邮件激活', '点击链接激活邮箱:' + url, from_email, rec_list, html_message='点击这个激活:'+html_msg)
@app.task()
def send():
send_mail('用户邮件激活', '点击链接激活邮箱:' + 'http://www.baidu.com',settings.DEFAULT_FROM_EMAIL, ['[email protected]', ])
@app.task()
def refresh():
print('refresh函数')
注意要在项目根目录下开启两个终端,按顺序执行,beat是定时任务启动
celery -A celery_tasks.main worker -l info
celery -A celery_tasks.main beat -l info