celery定时任务和异步任务的使用
记录一次在flask中对Celery的使用
celery是什么?
Celery 是一个由 Python 编写的简单、灵活、可靠的用来处理大量信息的分布式系统,它同时提供操作和维护分布式系统所需的工具。
说白了,它是一个分布式队列的管理工具,我们可以用 Celery 提供的接口快速实现并管理一个分布式的任务队列。
Brokers
brokers 中文意思为中间人,在这里就是指任务队列本身,Celery 扮演生产者和消费者的角色,brokers 就是生产者和消费者存放/拿取产品的地方(队列)
常见的 brokers 有 rabbitmq、redis
Workers
就是 Celery 中的工作者,类似与生产/消费模型中的消费者,其从队列中取出任务并执行
Tasks
就是我们想在队列中进行的任务咯,一般由用户、触发器或其他操作将任务入队,然后交由 workers 进行处理。
Backend
结果储存的地方,队列中的任务运行完后的结果或者状态需要被任务发送者知道,那么就需要一个地方储存这些结果
文件结构
(本文以 Celery4.3.0 为基础进行书写,Brokers使用rabbitmq)
具体说明
main.py
from __future__ import absolute_import
import os
import sys
from celery import Celery
from celery.utils.log import get_task_logger
BASE_PARH = os.path.dirname(os.path.dirname(__file__))
# 增加日志记录 方便日志查找问题
log = get_task_logger(__name__)
sys.path.insert(0, BASE_PARH)
app = Celery("自定义任务名")
app.config_from_object("tasks.config")
# 定义的任务
capp.autodiscover_tasks(["tasks.message_task"])
- sys.path.insert(0, BASE_PARH) 将当前路径添加到python环境变量,如果不导入其他自定义模块内容,可以忽略
- capp.config_from_object(“tasks.config”) 以文件的方式配置celery
- autodiscover_tasks 自动搜索任务,可以接收多个路径
config.py
from celery.schedules import crontab
# rabbitmq 配置worker
BROKER_URL = 'pyamqp://用户名:密码@rabbitmq IP地址:5672/虚拟主机'
# redis 配置worker
# BROKER_URL = 'redis://密码@IP地址:6390/1'
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERY_ENABLE_UTC = False
CELERYD_MAX_TASKS_PER_CHILD = 10
CELERY_IMPORTS = ("tasks",)
imports = [
"tasks.message_task", # 导入py文件
]
# 需要执行任务的配置
CELERYBEAT_SCHEDULE = {
'test1': {
# 具体需要执行的函数
# 该函数必须要使用@app.task装饰
'task': 'tasks.message_task.tasks.test1_run,
# 定时时间
# 每分钟执行一次,不能为小数
'schedule': crontab(minute='*/1'),
# 每小时执行一次
# "schedule": crontab(minute=0, hour="*/1")
# 执行的函数需要的参数
'args': ()
}
}
- CELERY_TIMEZONE 配置celery时区
- CELERY_ENABLE_UTC 是否启动UTC时间
- CELERYD_MAX_TASKS_PER_CHILD 配置worker执行多少任务后kill掉
- CELERY_IMPORTS 默认导入的任务文件名(最好不要改动)
- imports 导入定时任务
- test1 随意定义
- test1_run 任务名
tasks.py
配置自动搜索任务时文件名固定是tasks.py
import time
from tasks.main import app, log
def test11():
time.sleep(1)
print('test11')
def test22():
time.sleep(2)
print('test22')
test11()
@app.task
def test1_run():
test11()
test22()
@app.task
def test33(a,b):
print(a, b)
time.sleep(3)
print(a, b)
return a+b
- app.task 加task装饰器即可让方法变为异步任务
调用
和task文件夹同级目录下创建测试文件test.py
test.py
from tasks.message_task import test33
def test():
print("开始测试")
result = test33.delay(4, 4)
print("调用异步任务结束")
if __name__ == "__main__":
test()
delay 返回的是一个 AsyncResult 对象,里面存的就是一个异步的结果,当任务完成时result.ready() 为 true,然后用 result.get() 取结果即可。异步任务所需参数直接传递给delay即可
运行
启动worker
celery -A tasks.main worker -l info
- tasks.main 是启动celery文件,会自动搜索定义的任务
- worker 指定celery以worker运行
- -l 日志输入等级,同python日志定义相同
备注:这里启动如果报错,需要安装eventlet
安装方式: pip install eventlet
启动命令: celery-A tasks.main worker -l info -P eventlet
定时任务的使用
在tasks.py中我们定义了任务test1_run,我已经在config.py中将该义为定时任务,现在可以启动测试
启动
启动定时任务首先需要启动一个调度器
celery beat -A tasks.main -l info
然后在重新开一个命令窗口, 开启worker执行任务
celery -A tasks.main worker -l info -P eventlet
至此,celery的使用你已经学会了,更多高级用发需要参考官方文档
在实际应用我们需要celery在后台运行,celery提供了以linux守护进程的方式,启动方式:
celery multi start -A tasks.main worker -l info -P eventlet --logfile=celery.log
celery 的更多配置,点击这里