什么是 Celery?
Celery是一种简单、灵活、可靠的分布式系统,可以处理大量的消息,同时提供维护这种系统所需的工具
它是一个侧重于实时处理的任务队列,同时也支持任务调度。
Celery通过消息进行通信,通常使用代理在客户和工人之间进行调解。 为了启动一个任务,客户机向队列添加一条消息,然后代理将该消息传递给工作者。
核心概念
Task: 一个需要执行的任务,任务通常异步执行
Period Task: 需要定时执行的任务,定时一定间隔执行,也可以使用 crontab 表达式设定执 行周期和时间点
Message Broker: 消息代理,临时存储,传输任务到工作节点的消息队列。可以用 Redis, RabbitMQ, Amazon SQS 作为消息代理。消息代理可以有多个,以保障系统的高可用。
Worker:工作节点,执行任务的进程,worker可以有多个,保障系统的高可用和扩展性
Result Store: 结果存储
Scheduler/Beat: 调度器进程, Beat是定时任务调度器
大量需要使用异步任务的场景
- 发送电子邮件,发送 IM 消息通知
- 爬取网页, 数据分析
- 图像、视频处理
- 生成报告,深度学习
任务队列
-
任务队列用作在线程或计算机之间分配工作的机制。
-
任务队列的输入是一个称为任务的工作单元。专用的工作进程不断监视任务队列,以便执行新的工作。
工作模型
不同语言的客户端/服务器端实现
高可用
安装
python3 -m pip install -U Celery
python3 -m pip install "celery[redis,auth,msgpack]"
工程结构 添加celery
配置消息代理(redis作为后端)
wangdalei_dj/celery/tasks.py
#!coding=utf-8
from celery import Celery
# 第一个参数 是当前脚本的名称,第二个参数 是 broker 服务地址
app = Celery('tasks', backend='redis://172.31.7.188', broker='redis://172.31.7.188')
# backend 异步任务的结果存放到backend
# broker 存储任务的系统 代理是谁
@app.task
def add(x, y):
return x + y
开启一个监听
celery -A tasks worker --loglevel=INFO
运行一个异步任务 wangdalei_dj/celery/run_task.py
#coding=utf-8
from tasks import add
result = add.delay(4, 4)
print('Is task ready: %s' % result.ready())
run_result = result.get(timeout=1)
print('task result: %s' % run_result)
celery 的web监控, Flower: Real-time Celery web-monitor
python3 -m pip install flower
celery -A tasks flower --broker=redis://@172.31.7.188:6379/0
Django 与 Celery 集成:异步任务
工作模型 Django 集成celery
主应用启动时 加载celery
wangdalei_dj/wangdalei/init.py
# 为了避免 导入的包油命名冲突
from __future__ import absolute_import, unicode_literals
# 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
__all__ = ('celery_app',)
在主应用中配置模块 wangdalei_dj/wangdalei/celery.py
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery, shared_task
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.base')
app = Celery('wangdalei')
# 配置文件 都以CELERY作为前缀
app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
修改setting wangdalei_dj/settings/develop.py
CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/1'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERYD_MAX_TASKS_PER_CHILD = 10
CELERYD_LOG_FILE = os.path.join(BASE_DIR, "logs", "celery_work.log")
CELERYBEAT_LOG_FILE = os.path.join(BASE_DIR, "logs", "celery_beat.log")
创建task异步任务 [send_dingtalk_message]
wangdalei_dj/interview/tasks.py
from __future__ import absolute_import, unicode_literals
from celery import shared_task
import logging
logger = logging.getLogger(__name__)
def send(message):
logger.info("send_dingtalk_message: [{}]".format(message))
@shared_task
def send_dingtalk_message(message):
send(message)
将task异步任务 [send_dingtalk_message] 关联到http 请求 响应中
启动worker程序
DJANGO_SETTINGS_MODULE=settings.develop celery --app wangdalei worker -l debug
启动web监控
DJANGO_SETTINGS_MODULE=settings.develop celery --app wangdalei flower --broker=redis://@172.31.7.188:6379/0
在页面导出excel文件
后台监控可以看到celery的任务信息