1.概念
Celery 是 python 编写的开源分布式任务队列框架。主要的做用就是用来实现异步任务以及定时任务。
2.理解及场景
2.1理解
我们常说的任务处理、事件处理其实都是一个生产者与消费者之间的关系,生产者就是逻辑类、逻辑函数;消费者则是我们调用类及函数的过程。
假设现在有一个饼干生产家A,有一个要买饼干的小孩B。那么B就需要等待A产出饼干他才能买。
他们的过程是:B->有需求要购买饼干,告诉A要买饼干->A接收B的请求,制作饼干->B等待A制作出饼干->B获得饼干
他们是生产者跟消费者的关系,同时也是一个耦合的关系。
那么celery在这个过程中扮演的角色是一个 外卖小哥C
因为小孩B不想一直在等待厂家A生产,小孩B关心跟目的只有我要拿到饼干。这个时候外卖小哥C就出来替小孩B去等待了。这样一来小孩B就可以去利用生产饼干的事件去玩。
他们的过程是
B->有需求要购买饼干,告诉C要买饼干->C收到请求,把订单记录好然后告诉A要买饼干->A接收C的请求制作饼干->C等待A制作出饼干->C获得饼干->C把饼干放到B指定的地方->B获得饼干。
这样就可以理解celery的做用就是一个传输的角色
2.2场景
现在有一个运维系统,运维系统有一个功能是批量执行命令,你现在要对1000台设备执行
#通过网络同步Linux时间
ntpdate cn.pool.ntp.org
这个操作需要等待好长时间,并且你的运维系统要等它们执行完才会有响应跟做其他的事情。现在我不想等待这么长的时候,我只关心执行后的结果。
解决办法:
运维系统引用celery,用来做异步任务执行。
3.celery的优点
- 配置简单
- 高可用执行任务 (任务失败或中断会重新执行)
- 性能高、吞吐量大 (每分钟可以处理百万级任务)
- 任务情况清晰 (每个任务的结果、返回直观清晰,还有flower可视化监控组件支持)
- 解耦、高复用
4.celery组件
- Beat : 定时任务器;Beat进程会读取配置文件的内容,周期性的将配置中到期需要执行的任务发送给任务队列.
- Worker : 执行任务的消费者, 通常会在多台服务器运行多个消费者, 提高运行效率.
- Broker : 任务队列本身,也称为消息中间件.接受任务消费者发送过来的任务消息, 存进队列再按序分发给生产者(通常是消息队列或者数据库).
- Producer : 任务生产者.调用 Celery API,函数或者装饰器,而产生任务并交给任务队列处理的都是任务生产者.
- Result Backend : 任务处理完成之后保存状态信息和结果, 以供查询.
4.celery架构
5.Django应用Celery
5.1环境准备
##Django==3.1
pip install celery==5.1.2
pip install redis==3.5.3
yum install -y redis
(redis版本为4.0.9)
5.2应用
在/Prj/Prj 目录下创建 celery_init.py、celery_config.py、tasks.py
celery_init.py (实例化celery)
from celery import Celery
## 实例化celery,配置可作为参数传入
## broker,backend分别为消息队列以及任务结果存放的地方;timezone是使用的时区,imports是注册任务模块
app = Celery('Prj', broker='redis://127.0.0.1:6379/1', backend='redis://127.0.0.1:6379/2',
timezone='Asia/Shanghai',
imports=('Prj.tasks',
)
)
# 也可以自定义celery配置文件,celery_config就是配置文件
# app.config_from_object('celery_config', namespace='CELERY')
celery_config.py(如果定义实例传参作为配置则不需要这个配置文件)
broker_url = 'redis://127.0.0.1:6379/1'
result_backend = 'redis://127.0.0.1:6379/2'
timezone = 'Asia/Shanghai'
imports = ('Prj.tasks',)
###更多配置查看官网https://docs.celeryproject.org/en/latest/userguide/configuration.html
tasks.py (测试的tasks,即生产者)
from celery import shared_task
@shared_task
def test_task(a):
return a
项目的__init__.py(说明Django引入celery实例)
from __future__ import absolute_import, unicode_literals
from Prj import celery_init
app = celery_init.app
__all__ = ('app',)
启动celery
###启动celery的路径也有讲究,因为关于celery配置的路径全部是以celery启动的路径开始计算!!不然就很容易出现说你tasks未注册或者无法找到模块的报错
cd /.../Prj/Prj
celery -A Prj.celery_init worker -B -l info --beat
View 调用 tasks
from Prj import tasks
task = tasks.test_task.delay(4)
print(task.get())
返回结果(redis中结果)
{
status:"SUCCESS"
result:4
traceback:null
children:[]
date_done:"2021-10-27T07:23:28.438934"
task_id:"6fd47f60-98f5-40ec-93c0-0f45938d88dc"
}
5.3 flower应用
安装flower
pip install flower
启动flower
cd /.../Prj/Prj
celery -A Prj.celery_init flower
访问flower
http://ip:5555
6.使用supervisor管理celery与flower进程
安装supervisor
pip install supervisor
初始化配置
echo_supervisord_conf > /etc/supervisord.conf
配置
vim /etc/supervisord.conf
(在最后添加以下内容)
[program:celery] #管理进程名
directory=/opt/Prj/Prj #项目目录
command=celery -A Prj.celery_init worker -B -l info --beat #启动命令
autostart=true #自启动
autorestart=true #自动重启
stdout_logfile=/var/log/celery.log #正确输出日志
stderr_logfile=/var/log/celery.log #错误输出日志
loglevel=info #日志等级
[program:flower]
directory=/opt/Prj/Prj
command=celery -A Prj.celery_init flower
autostart=true
autorestart=true
stdout_logfile=/var/log/flower.log
stderr_logfile=/var/log/flower.log
loglevel=info
启动supervisor
supervisord -c /etc/supervisord.conf
supervisorctl -c /etc/supervisord.conf
常见命令
supervisorctl status #查看所有进程的状态
supervisorctl stop celery #停止es
supervisorctl start celery #启动es
supervisorctl restart celery #重启es
supervisorctl update #配置文件修改后使用该命令加载新的配置
supervisorctl reload #重新启动配置中的所有程序