Python 异步任务队列 Celery 使用

Python 异步任务队列 Celery 使用

tags:

  • python
  • 慕课网

categories:

  • python
  • Celery
  • RabbitMQ
  • flower
  • 进程管理supervisor

第一节 Celery简介

1. Celery介绍

  1. Celery是python中使用比较多的并行分布式框架 Celery 。
  2. Celery 是-一个简单、灵活且可靠的,处理大量消息的分布式系统
  3. 专注于实时处理的异步任务队列
  4. 同时也支持任务调度
  5. 官方文档中文版:http://docs.jinkan.org/docs/celery/
  6. 官方文档英文版:http://docs.celeryproject.org/en/latest/index.html
  7. celery配置:http://docs.jinkan.org/docs/celery/configuration.html#configuration
  8. CSDN借鉴:https://blog.csdn.net/cuomer/article/details/81214438
    在这里插入图片描述

2. Celery使用场景

  1. 异步任务:将耗时操作任务提交给Celery去异步执行,比如发送短信/邮件、消息推送、音视频处理等等。
  2. 定时任务:类似于crontab ,比如每日数据统计

第二节 Celery环境安装

  1. pip install celeryredis
  2. 消息中间件: RabbitMQ / Redis(官方推荐RabbitMQ)
  3. 安装虚拟环境(环境隔离):pip install virtualenvwrapper-win
  4. 如果需要对pyhton2和python3 版本环境方便切换。可以安装pyenv
  5. pyenv安装:https://github.com/pyenv/pyenv-installer
  6. curl -L https://github. com/ pyenv/ pyenv- installer/raw/master/bin/pyenv- installerI bash

第三节 Celery使用

1. Celery的基本使用

  1. pip install celery[redis]
  2. flask:app = Celery(‘xxx’, backend= Xxxxx’, broker= Xxxxx’)
  3. 这里有个坑.win10系统启动worker报错ValueError: not enough values to unpack (expected 3, got 0):
  4. 解决方法:
    • 安装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 ...")
  1. 把延时操作变成异步操作.
# 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
  1. 运行app.py 生产任务, 在当前文件夹下打开worker。celery -A task worker -l info -P eventlet.可以看到函数输出。
    在这里插入图片描述
  2. 可以查看执行结果:result.ready() # True执行完毕。 result.get() 获取执行结果:10

2. Celery的配置文件配置异步任务

  1. 官方配置文档:http://docs.celeryproject.org/en/latest/userguide/configuration.html
  2. CSDN配置博客:https://blog.csdn.net/qq_33961117/article/details/100770533
  3. 目录结构如下图:
    在这里插入图片描述
  4. 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
  1. 参数配置文件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',
)
  1. 耗时任务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
  1. 入口启动文件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的定时任务

  1. 这里只需修改上面配置文件即可。
  2. 启动定时任务前,先启动worker celery -A celery_app worker -l info -P eventlet
  3. 启动定时任务: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

  1. 安装django-celery: pip install django-celery
  2. 启动Worker命令: python manage.py celery worker -Q queue
  3. 启动一个django 项目:django-admin startproject django_celery
  4. 在创建一个任务app: django-admin startapp course。在django_celery中注册。
  5. 在 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 ')
  1. 在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
  1. 导入第六步的配置到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
  1. 在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'})
  1. window下启动celery worker: python manage.py celery worker -l INFO -P eventlet
  2. 启动服务器 python manage.py runserver. 输入网址:http://127.0.0.1:8000/do/
  3. redis 3.2.2时:报错 AttributeError: ‘str’ object has no attribute ‘items’。redis版本太高,降低版本 pip install redis==2.10.6
  4. 设置一个定时任务在django_celery中celeryconfig.py配置文件加入
# 这里指定队列为'beat_tasks'
CELERYBEAT_SCHEDULE = {
    # 每过10秒执行以下task1.add的定时任务
    'task1':{
        'task': 'course-task',
        'schedule': timedelta(seconds=10),
        'options':{
            'queue': 'beat_tasks'
        }
    },
}
  1. 启动定时任务:python manage.py celery beat -l INFO
  2. apply_async与delay相比 传参数比较方便: CourseTask.apply_async(args=(‘hello’,), queue=‘work_queue’)

第五节 Celery的部署和监控

1. 监控工具flower

  1. 安装: pip install flower
  2. 启动:celery flower --address=0.0.0.0 --port= 5555 --broker= XXXX --basic_auth=imooc:imooc
  3. broker 是指broker的url,basic_auth不想别人访问可以加认证
  4. django 项目中直接输入:python manage.py celery flower。 可以读取配置中的一些信息
  5. 输入http://localhost:5555 启动我们的celery任务可以在浏览器中看到执行信息
  6. 加账户和密码:python manage.py celery flower --basic_auth=imooc:imooc

2. 进程管理: supervisor

  1. 安装: pip install supervisor
  2. 启动配置文件:supervisord -C /etc/supervisord.conf
  3. 命令行管理工具:supervisorctl
  4. 项目django_celery下新建conf目录,把相关配置放到conf下面去。
  5. 输入命令:echo_supervisord_conf > conf/supervisord.conf 把supervisor的配置文件重新定向到我们的项目目录中。
  6. 官方文档:http://supervisord.org/
  7. 开启页面控制台管理(去掉前面的;):
[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
  1. 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 ;优先级
  1. 启动supervisoer. supervisord -C conf/supervisord.conf (在linux上操作吧,windows 有坑。草,上述配置酌情更改)
  2. ps -ef Igrep supervisor 查看进程是否存在
  3. supervisorctl调出命令行工具,help可以查看具体用法
  4. 127.0.0.1:9001可以看到可视化管理界面
  5. 在建一个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 ;优先级
  1. 命令行中更新一下:update 就把beat也加到我们的进程组中了。
  2. 同理,添加一下我们之前的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 ;优先级(越大越先启动)

第六节 总结

  1. 进程管理工具主要用来管理我们的进程。使用docker单独跑在一个容器中也是可行的。
  2. 但是进程管理supervisor更加成熟。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值