Celery异步任务搭建
Celery是一个简单、灵活且可靠的,处理大量消息的分布式系统,专注于实时处理的异步任务队列,同时也支持任务调度。
Celery的架构由三部分组成,消息中间件(message broker),**任务执行单元(worker)和任务执行结果存储(task result store)**组成。
消息中间件
Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成。包括,RabbitMQ, Redis等等
任务执行单元
Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中。
任务结果存储
Task result store用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括AMQP, redis等
另外, Celery还支持不同的并发和序列化的手段
- 并发:Prefork, Eventlet, gevent, threads/single threaded
- 序列化:pickle, json, yaml, msgpack. zlib, bzip2 compression, Cryptographic message signing 等等
搭建步骤
Windows下使用celery模块,不太好用的样子
方法一(使用djcelery)
1、安装djcelery模块
pip install redis==2.10.6 # 否则出现版本不契合的问题
pip install django-celery
2、setting中配置celery相关信息
import djcelery # 导包
djcelery.setup_loader() # 初始化celery异步任务
BROKER_URL = 'redis://127.0.0.1:6379/1' # 消息中间件,任务存放的redis容器地址
CELERY_IMPORTS = ('OneApp.tasks') # 指定celery任务文件
CELERY_TIMEZONE = 'Asia/Shanghai' # Celery定时任务使用的时区
CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler' # Celery调度程序
3、项目主目录中创建celery.py文件
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from django.conf import settings
# 把 Celery 和 Django进行结合,识别和加载 Django 的配置文件
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DJCelery.settings')
# 创建Celery实例对象
appCelery = Celery('appCelery')
# 通过appCelery对象加载配置
appCelery.config_from_object('django.conf:settings')
# 如果在app有创建tasks.py文件,会自动检索
appCelery.autodiscover_tasks(lambda :settings.INSTALLED_APPS)
4、创建celery任务,子应用中创建tasks.py文件,编写celery任务
from __future__ import absolute_import
import time
from DJCelery.celery import appCelery
# celery任务通常就是一个函数,只是在功能函数上添加了@appCelery.task装饰器
@appCelery.task
def send_email(name):
print('给%s发送邮件' % name)
time.sleep(5)
print('邮件发送完成:%s' % name)
return 'OK'
5、views视图调用异步、定时任务
from django.shortcuts import render, HttpResponse
from CeleryTest.tasks import send_email
from datetime import datetime, timedelta
# Create your views here.
def test(request):
# 创建异步任务
resultEmail = send_email.delay('119')
print(resultEmail)
# 创建定时任务
cTime = datetime.now()
utcTime = datetime.utcfromtimestamp(cTime.timestamp()) # 将本地时间转换为时间戳,再转换为UTC(国标时间)时间
timeDelay = timedelta(seconds=30)
taskTime = utcTime + timeDelay
send_email.apply_async(args=['小明'], eta=taskTime)
return HttpResponse('OK')
6、第一次启动进行数据库迁移
python manage.py migrate
7、启动celery
python manage.py celery -A DJCelery worker -l info
# DJCelery:Django项目名
启动celery会报错:Python 3.7 将async这个单词定义为关键词,所以不能作为模块名称,这里我们需要对源代码修改
(1)将Python3.7中的async修改为asynchronous
(2)将所有报错文件中的async均修改为asynchronous
方法二(Windows + Django + celery模块,不太好使的样子)
1、安装celery、redis、eventlet模块
pip install celery
pip install redis
pip install eventlet
2、创建异步任务执行文件,asyncTasks.py
import celery
import time
backend = 'redis://127.0.0.1:6379/1'
broker = 'redis://127.0.0.1:6379/2'
# 创建实例化对象
appCelery = celery.Celery('test', backend=backend, broker=broker)
@appCelery.task
def sendEmail(name):
print('向%s发送邮件' % name)
time.sleep(3)
print('发送(%s)邮件已成功' % name)
return 'Ok'
2、celery配置文件,celery.py
""" Celery 配置信息 """
broker = 'redis://127.0.0.1:6379/2'
resultBackend = 'redis://127.0.0.1:6379/1'
3、启动文件,main.py
import os
from celery import Celery
# # Linux环境下配置
# # 创建Celery实例对象
# appCelery = Celery('appCelery')
# # 通过appCelery对象加载配置
# appCelery.config_from_object('myCelery.config')
# Windows环境下配置
# 创建实例对象并配置
appCelery = Celery('appCelery', broker='redis://127.0.0.1:6379/2', backend='redis://127.0.0.1:6379/1')
# 把 Celery 和 Django进行结合,识别和加载 Django 的配置文件
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DJCelery.settings.dev')
# 加载任务
# 参数必须为一个列表,里面的每一个任务都是任务的路径名称
appCelery.autodiscover_tasks(['myCelery.sms', 'myCelery.email'])
# 启动Celery的命令
# 强烈建议切换目录到CeleryTasks根目录下启动
# celery -A myCelery.main worker -l info -P eventlet
4、创建celery任务,/myCelery/email/task.py文件
import time
from myCelery.main import appCelery
@appCelery.task
def sendEmail(name):
print('向%s发送邮件' % name)
time.sleep(3)
print('发送(%s)邮件已成功' % name)
return 'Ok'
5、视图函数,views.py
from django.shortcuts import render, HttpResponse
from myCelery.email.tasks import sendEmail
# Create your views here.
def test(request):
# 创建异步任务
# resultSms = sendSms.delay("110")
resultEmail = sendEmail.delay('119')
# print(resultSms, resultEmail)
print(resultEmail)
return HttpResponse('OK')
6、创建查看任务执行结果文件,resultTask.py
from celery.result import AsyncResult
from CeleryTest.tasks import appCelery, sendEmail
async_result=AsyncResult(id="c6ddd5b7-a662-4f0e-93d4-ab69ec2aea5d", app=appCelery)
if async_result.successful():
result = async_result.get()
print(result)
# result.forget() # 将结果删除
elif async_result.failed():
print('执行失败')
elif async_result.status == 'PENDING':
print('任务等待中被执行')
elif async_result.status == 'RETRY':
print('任务异常后正在重试')
elif async_result.status == 'STARTED':
print('任务已经开始被执行')