Django中使用celery
名词说明:
Django: python的一个使用量较大的框架.
celery: 一个异步任务队列管理工具,也叫做分布式任务队列
需求:
django, celery, django-celery-beat
背景摘要:
最近项目重构时把发送短信独立成一个单独的功能函数,然而函数中存在等待时间以判定短信发送是否成功,所以在即时回复的接口中比如发送验证码的时候,不能直接调用发送短信函数,需要使用异步任务调用,由于结果在函数中已经做了记录,所以不需要返回值
1. 首先需要在项目中配置celery配置
在项目子目录下新建celeryconfig.py文件/或者直接在setting中添加celery配置
# Celery application definition
CELERY_BROKER_URL = 'redis://127.0.0.1:6379'
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379'
CELERY_ACCEPT_CONTENT = ['application/json'] # 指定任务接受的内容类型
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Shanghai'
# celery不能用root用户启动的话需要在主配置文件中添加platforms.C_FORCE_ROOT = True
CELERYD_CONCURRENCY # 并发worker数
CELERY_TASK_RESULT_EXPIRES # 任务过期时间:60 * 60
CELERYD_MAX_TASKS_PER_CHILD # 每个worker最多执行100个任务就会被销毁,可防止内存泄露
CELERYD_TASK_TIME_LIMIT # 单个任务的运行时间超过此值,否则会w被SIGKILL 信号杀死
2. 在项目子目录下新建celery.py文件,初始化celery对象
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from celery.schedules import crontab
# set the default Django settings module for the 'celery' program.
from celery.task import periodic_task
from hqrv_server.settings import logger
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '项目名.settings')
app = Celery('hqrv_server')
# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
# 定时任务
@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
pass
# Calls test('hello') every 30 seconds.
# sender.add_periodic_task(30.0, add.s(4, 5), name='add every 30')
# # Calls test('world') every 30 seconds
# sender.add_periodic_task(30.0, test.s('world'), expires=10)
#
# # Executes every Monday morning at 7:30 a.m.
# sender.add_periodic_task(
# crontab(hour=7, minute=30, day_of_week=1),
# test.s('Happy Mondays!'),
# )
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
@app.task
def add(x, y):
return x + y
if __name__ == '__main__':
app.start()
异步任务添加需要在响应模块内新建tasks.py文件,
from celery import shared_task
@shared_task()
def async_send_sms(*args):
"""
异步短信发送服务
调用方法:async_send_sms.apply_async(args=())
:return:
"""
return send_sms(*args)
如果要建立定时任务的话可以选择在setup_periodic_tasks内添加,也可以在配置文件中添加
CELERYBEAT_SCHEDULE = {
'schedule-test':{
'task':'App.task.test1', #定时执行的任务的函数名称
'schedule':timedelta(seconds=7) #定时执行的间隔时间
}
}
这里只介绍在setup_periodic_tasks内添加,两种方法只有添加方式不一样,最终结果都是一样的,
添加任务
# 定时任务
@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
pass
# Calls test('hello') every 30 seconds.
# sender.add_periodic_task(30.0, add.s(4, 5), name='add every 30')
# # Calls test('world') every 30 seconds
# sender.add_periodic_task(30.0, test.s('world'), expires=10)
#
# # Executes every Monday morning at 7:30 a.m.
sender.add_periodic_task(
crontab(hour=7, minute=30, day_of_week=1),
test.s('Happy Mondays!'),
)
# 关于crontab时间设置,
# crontab(minute='*', hour='*', day_of_week='*', day_of_month='*', month_of_year='*')
# 含义是每天、每小时、每分钟执行一次任务。也就是每分钟执行一次任务。
# 可以设定具体某个时间执行,例如 crontab(hour='1') 即每天凌晨1点执行
# 也可以设置多个值。 ,例如 crontab(hour='0, 1') 即每天凌晨0点, 1点各执行一次
# 每2个小时中每分钟执行1次任务 crontab(hour='*/2')
# 每3个小时的0分时刻执行1次任务 即[0,3,6,9,12,15,18,21]点0分 crontab(minute=0, hour='*/3')
# 每3个小时或8点到12点的0分时刻执行1次任务 即[0,3,6,9,12,15,18,21]+[8,9,10,11,12]点0分 crontab(minute=0, hour='*/3,8-12')
# 每个季度的第1个月中,每天每分钟执行1次任务 月份范围是1-12,每3个月为[1,4,7,10] crontab(month_of_year='*/3')
# 每月偶数天数的0点0分时刻执行1次任务 crontab(minute=0, hour=0, day_of_month='2-31/2')
# 每年5月11号的0点0分时刻执行1次任务 crontab(0, 0, day_of_month='11', month_of_year='5')
windows下开启celery服务命令:
celery -A 项目名 worker --loglevel=DEBUG -P eventlet # -Q 队列名
开启一个beat任务监控celery任务进行状态
celery -A 项目名 beat -l info
linux环境下开启celery服务命令
celery worker -A 项目名 --loglevel=INFO # -Q 队列名
celery beat -A 项目名 --loglevel=INFO