Python 异步任务队列 Celery 使用
tags:
- python
- 慕课网
categories:
- python
- Celery
- RabbitMQ
- flower
- 进程管理supervisor
文章目录
第一节 Celery简介
1. Celery介绍
- Celery是python中使用比较多的并行分布式框架 Celery 。
- Celery 是-一个简单、灵活且可靠的,处理大量消息的分布式系统
- 专注于实时处理的异步任务队列
- 同时也支持任务调度
- 官方文档中文版:http://docs.jinkan.org/docs/celery/
- 官方文档英文版:http://docs.celeryproject.org/en/latest/index.html
- celery配置:http://docs.jinkan.org/docs/celery/configuration.html#configuration
- CSDN借鉴:https://blog.csdn.net/cuomer/article/details/81214438

2. Celery使用场景
- 异步任务:将耗时操作任务提交给Celery去异步执行,比如发送短信/邮件、消息推送、音视频处理等等。
- 定时任务:类似于crontab ,比如每日数据统计
第二节 Celery环境安装
- pip install celeryredis
- 消息中间件: RabbitMQ / Redis(官方推荐RabbitMQ)
- 安装虚拟环境(环境隔离):pip install virtualenvwrapper-win
- 如果需要对pyhton2和python3 版本环境方便切换。可以安装pyenv
- pyenv安装:https://github.com/pyenv/pyenv-installer
- curl -L https://github. com/ pyenv/ pyenv- installer/raw/master/bin/pyenv- installerI bash
第三节 Celery使用
1. Celery的基本使用
- pip install celery[redis]
- flask:app = Celery(‘xxx’, backend= Xxxxx’, broker= Xxxxx’)
- 这里有个坑.win10系统启动worker报错ValueError: not enough values to unpack (expected 3, got 0):
- 解决方法:
- 安装pip install eventlet
- win10启动worker命令:celery -A task worker -l info -P eventlet
# app.py 模拟一个延时阻塞的任务
# 考虑设置add方法为异步方法,这里就不会阻塞。继续往下走
import time
# 模拟一个耗时的操作
def add(x, y):
print('Enter call function ...')
time.sleep(4)
return x + y
if __name__=='__main__':
print("Start Task ...")
result = add(2, 8)
print("result:", result)
print("End Task ...")
- 把延时操作变成异步操作.
# app.py
import time
from task import add
if __name__ == '__main__':
print("Start Task ...")
result = add.delay(2, 8)
print("result:", result)
print("End Task ...")
# Start Task ...
# result: c88a6fab-6923-4324-96e7-c1c8a36719d9
# End Task ...
# 这里并没有启动worker, 它只是把任务发给redis中
# -A tasks 是app实例的位置task.py
# -l info 是输出日志的级别为info
# win10有坑需要安装pip install eventlet不然报错ValueError: not enough values to unpack (expected 3, got 0)
# win10有坑启动worker:celery -A task worker -l info -P eventlet
# celery -A <mymodule> worker -l info -P eventlet
# task.py
import time
from celery import Celery
# 实例化一个Celery
broker = 'redis://localhost:6379/1'
backend = 'redis://localhost:6379/2'
# 参数1 自动生成任务名的前缀
# 参数2 broker 是我们的redis的消息中间件
# 参数3 backend 用来存储我们的任务结果的
app = Celery('my_task', broker=broker, backend=backend)
# 加入装饰器变成异步的函数
@app.task
def add(x, y):
print('Enter call function ...')
time.sleep(4)
return x + y
if __name__ == '__main__':
# 这里生产的任务不可用,导入的模块不能包含task任务。会报错
print("Start Task ...")
result = add.delay(2, 8)
print("result:", result)
print("End Task ...")
# Start Task ...
# result: c88a6fab-6923-4324-96e7-c1c8a36719d9
# End Task ...
# 这里并没有启动worker, 它只是把任务发给redis中
# -A tasks 是app实例的位置task.py
# -l info 是输出日志的级别为info
# win10有坑需要安装pip install eventlet不然报错ValueError: not enough values to unpack (expected 3, got 0)
# win10有坑启动worker:celery -A task worker -l info -P eventlet
# celery -A <mymodule> worker -l info -P eventlet
- 运行app.py 生产任务, 在当前文件夹下打开worker。celery -A task worker -l info -P eventlet.可以看到函数输出。

- 可以查看执行结果:result.ready() # True执行完毕。 result.get() 获取执行结果:10
2. Celery的配置文件配置异步任务
- 官方配置文档:http://docs.celeryproject.org/en/latest/userguide/configuration.html
- CSDN配置博客:https://blog.csdn.net/qq_33961117/article/details/100770533
- 目录结构如下图:

- init.py 包初始化文件
# __init__.py 包初始化文件
from celery import Celery
app = Celery('demo')
app.config_from_object('celery_app.celeryconfig') # 通过celery 实例加载配置文件
# celery -A celery_app worker -l info -P eventlet
- 参数配置文件celeryconfig.py
# 参数配置文件celeryconfig.py
BROKER_URL = 'redis://localhost:6379/1'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/2'
CELERY_TIMEZONE = "Asia/shanghai" #默认UTC
# 导入指定的任务模块
CELERY_IMPORTS = (
'celery_app.task1',
'celery_app.task2',
)
- 耗时任务task1 task2
# task1
import time
from celery_app import app
@app.task
def add(x, y):
print('Enter call function ...')
time.sleep(4)
return x + y
# task2
import time
from celery_app import app
@app.task
def multiply(x, y):
print('Enter call function ...')
time.sleep(4)
return x * y
- 入口启动文件app.py, 生产任务。生产任务前可以先打开worker:celery -A celery_app worker -l info -P eventlet
# app.py
import time
#from task import add
from celery_app import task1, task2
if __name__ == '__main__':
print("Start Task ...")
result1 = task1.add.delay(2, 8) # 或apply_async也可以
result2 = task2.multiply.delay(3, 8)
print("result1:", result1)
print("result2:", result2)
print("End Task ...")
3. Celery的定时任务
- 这里只需修改上面配置文件即可。
- 启动定时任务前,先启动worker celery -A celery_app worker -l info -P eventlet
- 启动定时任务:celery beat -A celery_app -l info
from datetime import timedelta
from celery.schedules import crontab
BROKER_URL = 'redis://localhost:6379/1'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/2'
CELERY_TIMEZONE = "Asia/shanghai" #默认UTC
# 导入指定的任务模块
CELERY_IMPORTS = (
'celery_app.task1',
'celery_app.task2',
)
# 设置定时任务
CELERYBEAT_SCHEDULE = {
# 每过10秒执行以下task1.add的定时任务
'task1':{
'task': 'celery_app.task1.add',
'schedule': timedelta(seconds=10),
'args': (2, 8)
},
# 等到22点18分执行task2的multiply
'task2': {
'task': 'celery_app.task2.multiply',
'schedule': crontab(hour=22, minute=20),
'args': (4, 5)
}
}
第四节 Django中使用Celery
- 安装django-celery: pip install django-celery
- 启动Worker命令: python manage.py celery worker -Q queue
- 启动一个django 项目:django-admin startproject django_celery
- 在创建一个任务app: django-admin startapp course。在django_celery中注册。
- 在 course应用下新建tasks.py
# tasks.py 耗时任务
import time
from celery.task import Task
class CourseTask(Task):
# 任务名称
name = 'course-task'
def run(self, *args, **kwargs):
print('start course task')
time.sleep(4)
print('args={}, kwargs={}'.format(args, kwargs))
print('end course task ')
- 在django_celery中新建celeryconfig.py配置文件。
# celeryconfig.py celery 配置文件
import djcelery
djcelery.setup_loader()
CELERY_IMPORTS = (
'course.tasks',
)
# 把定时任务和普通任务区分开,绑定到不同的队列中
CELERY_QUEUES = {
'beat_tasks': {
'exchange': 'beat_tasks',
'exchange_type': 'direct',
'binding_key': 'beat_tasks',
},
'work_queue': {
'exchange': 'work_queue',
'exchange_type': 'direct',
'binding_key': 'work_queue',
}
}
# 绑定默认队列为work_queue
CELERY_DEFAULT_QUEUE = 'work_queue'
# 有些情况可以防止死锁
CELERYD_FORCE_EXECV = True
#设置并发的worker数量
CELERYD_CONCURRENCY = 4
# 允许重试
CELERY_ACKS_LATE = True
#每个worker最多执行100个任务然后就被销毁,可以防止内存泄露(非常重要)
CELERYD_MAX_TASKS_PER_CHILD = 100
# 设置每一个任务的最大运行时间
CELERYD_TASK_TIME_LIMIT = 12 * 30
- 导入第六步的配置到django_celery的settings.py中
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'djcelery',
'course',
]
# Celery
from .celeryconfig import *
BROKER_BACKEND = 'redis'
BROKER_URL = 'redis://localhost:6379/1'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/2'
CELERY_TIMEZONE = "Asia/shanghai" #默认UTC
- 在cource的views.py中添加执行任务函数
# 在cource.views 中
from django.http import JsonResponse
from course.tasks import CourseTask
def do(request):
# 执行异步任务
print("do request")
CourseTask.delay()
print("end do request")
return JsonResponse({'result:': 'ok'})
- window下启动celery worker: python manage.py celery worker -l INFO -P eventlet
- 启动服务器 python manage.py runserver. 输入网址:http://127.0.0.1:8000/do/
- redis 3.2.2时:报错 AttributeError: ‘str’ object has no attribute ‘items’。redis版本太高,降低版本 pip install redis==2.10.6
- 设置一个定时任务在django_celery中celeryconfig.py配置文件加入
# 这里指定队列为'beat_tasks'
CELERYBEAT_SCHEDULE = {
# 每过10秒执行以下task1.add的定时任务
'task1':{
'task': 'course-task',
'schedule': timedelta(seconds=10),
'options':{
'queue': 'beat_tasks'
}
},
}
- 启动定时任务:python manage.py celery beat -l INFO
- apply_async与delay相比 传参数比较方便: CourseTask.apply_async(args=(‘hello’,), queue=‘work_queue’)
第五节 Celery的部署和监控
1. 监控工具flower
- 安装: pip install flower
- 启动:celery flower --address=0.0.0.0 --port= 5555 --broker= XXXX --basic_auth=imooc:imooc
- broker 是指broker的url,basic_auth不想别人访问可以加认证
- django 项目中直接输入:python manage.py celery flower。 可以读取配置中的一些信息
- 输入http://localhost:5555 启动我们的celery任务可以在浏览器中看到执行信息
- 加账户和密码:python manage.py celery flower --basic_auth=imooc:imooc
2. 进程管理: supervisor
- 安装: pip install supervisor
- 启动配置文件:supervisord -C /etc/supervisord.conf
- 命令行管理工具:supervisorctl
- 项目django_celery下新建conf目录,把相关配置放到conf下面去。
- 输入命令:echo_supervisord_conf > conf/supervisord.conf 把supervisor的配置文件重新定向到我们的项目目录中。
- 官方文档:http://supervisord.org/
- 开启页面控制台管理(去掉前面的;):
[inet_http_server] ; inet (TCP) server disabled by default
port=127.0.0.1:9001 ; ip_address:port specifier, *:port for all iface
;username=user ; default is no username (open server)
;password=123 ; default is no password (open server)
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
[include]
files = *.ini
- conf下新建自己的配置文件supervisor_celery_worker.ini
[program: django-celery-worker] ;配置worker启动进程
command=python manage.py celery worker -l INFO -P eventlet ;worker启动进程命令
directory=E:\python数据结构与算法-路飞学院\Python 异步任务队列 Celery 使用\django_celery ;启动命令执行目录
environment=PATH="E:\PY_ENV\py3-flask\Scripts" ;虚拟环境路径
stdout_logfile=E:\python数据结构与算法-路飞学院\Python 异步任务队列 Celery 使用\django_celery\log\celery_worker.log ;输出日志
stderr_logfile=E:\python数据结构与算法-路飞学院\Python 异步任务队列 Celery 使用\django_celery\log\celery_worker.log ;输出错误日志
autostart=true ;自动启动
autorestart=true ;自动重启
startsecs=10
stopwatisecs=60
priority=998 ;优先级
- 启动supervisoer. supervisord -C conf/supervisord.conf (在linux上操作吧,windows 有坑。草,上述配置酌情更改)
- ps -ef Igrep supervisor 查看进程是否存在
- supervisorctl调出命令行工具,help可以查看具体用法
- 127.0.0.1:9001可以看到可视化管理界面
- 在建一个beat的配置文件supervisor_celery_bear.ini
[program: django-celery-beat] ;配置beat启动进程
command=python manage.py celery beat -l INFO ;beat启动进程命令
directory=E:\python数据结构与算法-路飞学院\Python 异步任务队列 Celery 使用\django_celery ;启动命令执行目录
environment=PATH="E:\PY_ENV\py3-flask\Scripts" ;虚拟环境路径
stdout_logfile=E:\python数据结构与算法-路飞学院\Python 异步任务队列 Celery 使用\django_celery\log\celery_beat.log ;输出日志
stderr_logfile=E:\python数据结构与算法-路飞学院\Python 异步任务队列 Celery 使用\django_celery\log\celery_beat.log ;输出错误日志
autostart=true ;自动启动
autorestart=true ;自动重启
startsecs=10
stopwatisecs=60
priority=997 ;优先级
- 命令行中更新一下:update 就把beat也加到我们的进程组中了。
- 同理,添加一下我们之前的flower进程supervisor_celery_flower.ini。
[program: django-celery-flower] ;配置flower启动进程
command=python manage.py celery flower ;flower启动进程命令
directory=E:\python数据结构与算法-路飞学院\Python 异步任务队列 Celery 使用\django_celery ;启动命令执行目录
environment=PATH="E:\PY_ENV\py3-flask\Scripts" ;虚拟环境路径
stdout_logfile=E:\python数据结构与算法-路飞学院\Python 异步任务队列 Celery 使用\django_celery\log\celery_flower.log ;输出日志
stderr_logfile=E:\python数据结构与算法-路飞学院\Python 异步任务队列 Celery 使用\django_celery\log\celery_flower.log ;输出错误日志
autostart=true ;自动启动
autorestart=true ;自动重启
startsecs=10
stopwatisecs=60
priority=1000 ;优先级(越大越先启动)
第六节 总结
- 进程管理工具主要用来管理我们的进程。使用docker单独跑在一个容器中也是可行的。
- 但是进程管理supervisor更加成熟。
647

被折叠的 条评论
为什么被折叠?



