Celery的中文文档: http://docs.jinkan.org/docs/celery/getting-started/first-steps-with-celery.html#first-steps
本次实例是基于Django的应用
celery的简单介绍
Celery是一个异步的任务队列(也叫做分布式任务队列)
Celery 是一个专注于实时处理和任务调度的分布式任务队列, 同时提供操作和维护分布式系统所需的工具… 所谓任务就是消息, 消息中的有效载荷中包含要执行任务需要的全部数据.
Celery 是一个分布式队列的管理工具, 可以用 Celery 提供的接口快速实现并管理一个分布式的任务队列.
Celery 本身不是任务队列, 是管理分布式任务队列的工具. 它封装了操作常见任务队列的各种操作, 我们使用它可以快速进行任务队列的使用与管理.
Celery 特性 :
- 方便查看定时任务的执行情况, 如 是否成功, 当前状态, 执行任务花费的时间等.
- 使用功能齐备的管理后台或命令行添加,更新,删除任务.
- 方便把任务和配置管理相关联.
- 可选 多进程, Eventlet 和 Gevent 三种模型并发执行.
- 提供错误处理机制.
- 提供多种任务原语, 方便实现任务分组,拆分,和调用链.
- 支持多种消息代理和存储后端.
- Celery 是语言无关的.它提供了python 等常见语言的接口支持.
celery 组件
- Celery 扮演生产者和消费者的角色,
- Celery Beat : 任务调度器. Beat 进程会读取配置文件的内容, 周期性的将配置中到期需要执行的任务发送给任务队列.
- Celery Worker : 执行任务的消费者, 通常会在多台服务器运行多个消费者, 提高运行效率.
- Broker : 消息代理, 队列本身. 也称为消息中间件. 接受任务生产者发送过来的任务消息, 存进队列再按序分发给任务消费方(通常是消息队列或者数据库).
- Producer : 任务生产者. 调用 Celery API , 函数或者装饰器, 而产生任务并交给任务队列处理的都是任务生产者.
- Result Backend : 任务处理完成之后保存状态信息和结果, 以供查询.
流程示意图
安装Celery
同时需要安装中间人broker,通常是RabbitMQ或者Redis,自行百度安装
这是redis和celery同时安装:
pip install -U "celery[redis]"
安装RabbitMQ:
sudo apt-get install rabbitmq-server
运行celery
celery -A 模块名 worker -l info
运行成功的标识
简单的使用celery
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()
接下来,我们要在Django项目中配置相关内容
在项目下创建文件夹celery_tasks,在里面创建要使用的模块和相关配置文件
在config.py中配置以下文件
#配置文件
broker_url = "redis://127.0.0.1/4" #4 指的是redis数据库的4号库
在main.py文件中配置以启动文件
#启动文件的配置
from celery import Celery
#告知celery 使用django的配置文件进行配置
import os
if not os.getenv('DJANGO_SETTINGS_MODULE'):
os.environ['DJANGO_SETTINGS_MODULE'] = 'shanghui.settings.dev'
#创建应用
app = Celery('shanghui')
#导入celery的配置文件
app.config_from_object('celery_tasks.config')
#任务
app.autodiscover_tasks(['celery_tasks.msg','celery_tasks.email'])
接下来我们简单用一下celery和redis配合使用解决邮箱验证和短信验证的耗时操作
发送验证邮件实例
在celery_tasks文件中创建email文件夹并在email文件夹中创建tasks.py书写真正任务的文件
#真正书写任务
#在当前的tasks里面书写邮件发送任务
from django.core.mail import send_mail
from django.conf import settings
from celery_tasks.main import app
@app.task(name='send_mail')
def send_email(email,url_string):
subject = '尚惠欢迎信息'
# 邮件信息,正文部分
message = '欢迎'
# 发送者,直接从配置文件中导入上面配置的发送者
sender = settings.EMAIL_FROM
# 接收者的邮箱,是一个列表,这里是前端用户注册时传过来的 email
receiver = [email, ]
# html结构的信息,其中包含了加密后的用户信息token
html_message = url_string
# 调用Django发送邮件的方法,这里传了5个参数
send_mail(subject, message, sender, receiver, html_message=html_message)
在serializers.py文件中修改为:
from celery_tasks.email.tasks import my_send
# todo 发送邮件
url_string = '<a href=' + url + '>点击链接</a>'
to_email_url = validated_data['email']
# todo 发送邮件需要使用的是celery来发送,就将这个任务加到队列中去
try:
send_email.delay(to_email_url,url_string)
except Exception as e:
print(e)
return instance
发送短信验证码实例
创建celery_task文件夹—>msg文件夹—>tasks.py文件
#真正书写任务
#在当前的tasks里面书写邮件发送任务
from shanghui.libs.yuntongxun.sms import CCP
from celery_tasks.main import app
from shanghui.apps.images import constants
@app.task(name='send_mag')
def send_msg(phone,msg):
# todo 5.发送短信
ccp = CCP()
result = ccp.send_template_sms(phone, [msg, constants.PHONE_FLAG_CODE_EXPIRES], 1)
在view.py文件中修改为:
# todo 5.发送短信
send_msg.delay(phone,msg)
return Response({"message": "ok"})
修改完以后在终端中运行celery
celery -A 模块名 worker -l info
flower模块
flower 是一个 celery 的监控工具,它提供了一个图形用户界面,可以极大的方便我们监控任务的执行过程, 执行细节及历史记录,还提供了统计功能。
flower 安装
pip install flower
flower 使用简介,首先启动通过命令行启动 flower 进程:
flower -A proj --port=5555
celery定时任务(计划任务)
还是在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, ['paul0926@foxmail.com', ])
@app.task()
def refresh():
print('refresh函数')
启动定时任务:
注意要在项目根目录下开启两个终端,按顺序执行,beat是定时任务启动
celery -A celery_tasks.main worker -l info
celery -A celery_tasks.main beat -l info
项目目录图: