CELERY 定时任务

1. 介绍

Celery是一个强大的分布式任务队列,他可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行。通常用来实现异步任务和定时任务。异步任务比如发送邮件,文件上传图像处理等;定时任务就是需要在特定时间执行的任务。


  • 任务队列
    任务队列是一种跨线程,跨机器工作的一种机制,任务队列中包含称作任务的工作单元。有专门的工作进程持续不断的监视任务队列,并从中获取新的任务并处理。
  • 任务模块
    包含异步任务和定时任务。异步任务通常在业务逻辑中被触发并发往任务队列;定时任务由Celery Beat进程周期性地将任务发往任务队列。
  • 消息中间件Broker
    Broker,就是任务调度队列,接收任务生产者发来的消息(任务),将任务存入到队列。Celery本身不提供队列服务,官方推荐使用RabbitMQ和Redis等。
  • 任务执行单元Worker
    Worker是执行任务的处理单元,它实时监控消息队列,获取队列中调度的任务,并执行它。
  • 任务结果存储Backend
    Backend用于存储任务的执行结果,以供查询。同消息中间件一样,也可使用RabbitMQ和Redis,MySql等。

2. 使用步骤

2.1 使用Celery实现异步任务

a. 创建Celery实例
b. 启动Celery Worker,通过delay()或者apply_async()将任务发布到broker
c. 应用程序调用异步任务
d. 存储结果
Celery Beat: 任务调度器,Beat进程会读取配置文件的内容,周期性的将配置中到期需要执行的任务发送给任务队列

2.2 使用Celery定时任务

a. 创建Celery实例
b. 配置文件中配置任务,发送任务celery -A xxx beat
c. 启动Celery Worker celery -A xxx worker -l info -P eventlet
d. 存储结果

3. 代码实现

3.1 test1.py

from .. import app
import time


def test11():
    time.sleep(1)
    print('test11')


def test22():
    time.sleep(2)
    print('test22')
    test11()


@app.task
def test1_run():
    test11()
    test22()

3.2 test2.py

from .. import app
import time


def test33():
    time.sleep(3)
    print('test33')


def test44():
    time.sleep(4)
    print('test44')
    test33()


@app.task
def test2_run():
    test33()
    test44()

3.3 celery_task.__init__.py

# 拒绝隐式引入,如果celery.py和celery模块名字一样,避免冲突,需要加上这条语句
# 该代码中,名字是不一样的,最好也要不一样
from __future__ import absolute_import
from celery import Celery

app = Celery('tasks')
app.config_from_object('celery_task.celeryconfig')

3.4 celeryconfig.py

from __future__ import absolute_import
from celery.schedules import crontab
from datetime import timedelta

# 使用redis存储任务队列
broker_url = 'redis://127.0.0.1:6379/7'
# 使用redis存储结果
result_backend = 'redis://127.0.0.1:6379/8'

task_serializer = 'json'
result_serializer = 'json'
accept_content = ['json']
# 时区设置
timezone = 'Asia/Shanghai'
# celery默认开启自己的日志
# False表示不关闭
worker_hijack_root_logger = False
# 存储结果过期时间,过期后自动删除
# 单位为秒
result_expires = 60 * 60 * 24

# 导入任务所在文件
imports = [
    'celery_task.app_scripts.test1',
    'celery_task.app_scripts.test2'
]

# 需要执行任务的配置
beat_schedule = {
    'test1': {
        # 具体需要执行的函数
        # 该函数必须要使用@app.task装饰
        'task': 'celery_task.app_scripts.test1.test1_run',
        # 定时时间
        # 每分钟执行一次,不能为小数
        'schedule': crontab(minute='*/1'),
        # 或者这么写,每小时执行一次
        # "schedule": crontab(minute=0, hour="*/1")
        # 执行的函数需要的参数
        'args': ()
    },
    'test2': {
        'task': 'celery_task.app_scripts.test2.test2_run',
        # 设置定时的时间,10秒一次
        'schedule': timedelta(seconds=10),
        'args': ()
    }
}

如果大写的话,需要写成:

CELERYBEAT_SCHEDULE = {
    'celery_app.task.task1': {
        'task': 'celery_app.task.task1',
        'schedule': timedelta(seconds=20),
        'args': (1, 10)
    },
    'celery_app.task.task2': {
        'task': 'celery_app.task.task2',
        'schedule': crontab(minute='*/2'),
        'args': ()
    }
}

4. 执行定时任务

4.1 发布任务

在celery_task同级目录下,执行命令:
celery -A celery_task beat

4.2 执行任务

在celery_task同级目录下,执行命令:
celery -A celery_task worker -l info -P eventlet
可以看到输出:

[2018-09-07 16:54:57,809: WARNING/MainProcess] test33
[2018-09-07 16:55:00,002: INFO/MainProcess] Received task: celery_task.app_scrip
ts.test1.test1_run[0134cb52-29a3-4f57-890e-9730feac19e7]
[2018-09-07 16:55:01,069: WARNING/MainProcess] test11
[2018-09-07 16:55:01,821: WARNING/MainProcess] test44
[2018-09-07 16:55:03,083: WARNING/MainProcess] test22
[2018-09-07 16:55:04,234: WARNING/MainProcess] test11

如果同时在<b>两个虚拟环境(服务器)</b>中都执行定时任务,都可以看到有以上LOG打印。

4.3 celery相关命令

发布任务
celery -A celery_task beat
执行任务
celery -A celery_task worker -l info -P eventlet
将以上两条合并
celery -B -A celery_task worker
后台启动celery worker进程
celery multi start work_1 -A appcelery
停止worker进程,如果无法停止,加上-A
celery multi stop WORKNAME
重启worker进程
celery multi restart WORKNAME
查看进程数
celery status -A celery_task

4.4 定时方式

from celery.schedules import crontab
from datetime import timedelta

# 1 每10秒钟执行一次
'schedule':timedelta(seconds=30)

# 2 每分钟执行一次
'schedule':crontab(minute='*/1') 

5.参考

https://blog.csdn.net/Shyllin/article/details/80940643
https://blog.csdn.net/zhangfh1990/article/details/77164499
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容