celery task


前言

讨论一个定时任务,一般而言,需要的功能如下:

  1. 封装成对象,独立执行;
  2. 对象有一些接口,便于了解它的状态;
  3. 定时调用;
  4. 行为控制,包括重试,成功/失败回调等;

下面分别介绍celery的这些功能实现。

1.task basic

celery的task基础类是tasks.Task()

1.1 bound tasks

绑定代表第一个参数默认是self

  1. logger = get_task_logger(__name__)
  2.  
  3. @task(bind=True)
  4. def add(self, x, y):
  5. logger.info(self.request.id)

1.2 Task类继承

需要注意的是声明的位置,是在把方法修饰成Task类时声明。

  1. @app.task(base=MyTask)
  2. def add(x, y):
  3. #raise KeyError
  4. return x + y

1.3 names

每个task实例都有一个非重复的名字,譬如下例:

  1. @app.task(name='tasks.mul')
  2. def mul(x, y):

一般不必要使用这一功能,特别是在task方法放在单独的module中时,默认name就是module name+方法名(celery_tasks.mul)。

尽量不要把任务模块命名为tasks.py,命名为celery_1.py更好一些。

1.4 其它属性

Task.max_retries 最大重试次数

Task.default_retry_delay 默认重试等待时间。

Task.ignore_result 抛弃结果,意味着不能通过 AsyncResult查看结果。

2.task 自定义任务行为

文档:http://docs.celeryproject.org/en/latest/userguide/tasks.html#custom-task-classes

主要有四种,包括失败/成功/重试/完成

on_failure on_success on_retry after_return

  1. # celery_tasks.py
  2. class MyTask(Task):
  3. def on_success(self, retval, task_id, args, kwargs):
  4. print 'task done: {0}'.format(retval)
  5. return super(MyTask, self).on_success(retval, task_id, args, kwargs)
  6.  
  7. def on_failure(self, exc, task_id, args, kwargs, einfo):
  8. print 'task fail, reason: {0}'.format(exc)
  9. return super(MyTask, self).on_failure(exc, task_id, args, kwargs, einfo)
  10.  
  11. @app.task(base=MyTask)
  12. def add(x, y):
  13. return x + y

2.1 retry

app.Task.retry() 是实现重试的方法。

  1. # an example of using retry:
  2. @app.task(bind=True)
  3. def send_twitter_status(self, oauth, tweet):
  4. try:
  5. twitter = Twitter(oauth)
  6. twitter.update_status(tweet)
  7. except (Twitter.FailWhaleError, Twitter.LoginError) as exc:
  8. raise self.retry(exc=exc)

可以指定重试间隔时间,默认为180秒,下面案例指定为1800秒。

  1. @app.task(bind=True, default_retry_delay=30 * 60) # retry in 30 minutes.
  2. def add(self, x, y):

关于最大重试次数等参数是在task实例中指定。

3. 定时执行 periodic task

文档:http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html

celery beat is a scheduler。

默认的参数源自beat_schedule。

3.1 时区

调度器默认使用UTC时区,当然需要修改:

timezone = 'Europe/London'

或 app.conf.timezone = 'Europe/London'

3.2 entries

有两种添加定时任务的方式,装饰器和配置文件。

常用配置文件方式。

3.2.1 从配置文件中读取定时任务

celery_config.py # 配置文件

  1. #!/usr/bin/env python
  2. #coding:utf-8
  3.  
  4. """
  5. celery configure
  6.  
  7. """
  8. #__author__ = 'sss'
  9.  
  10. from __future__ import absolute_import
  11. from celery.schedules import crontab
  12. from datetime import timedelta
  13.  
  14. # 使用redis存储任务队列及结果
  15. broker_url = 'redis://:123@192.168.199.113:6379/0'
  16. result_backend = 'redis://:123@192.168.199.113:6379/1'
  17.  
  18. task_serializer = 'json'
  19. result_serializer = 'json'
  20. accept_content = ['json']
  21.  
  22. # 时区
  23. timezone = 'Asia/Shanghai'
  24.  
  25. # celery默认开启自己的日志
  26. # False表示不关闭
  27. worker_hijack_root_logger = False
  28. # 存储结果过期时间,过期后自动删除
  29. # 单位为秒
  30. result_expires = 60 * 60 * 24
  31.  
  32. # 导入任务所在文件
  33. imports = [
  34. 'celery_tasks',
  35. ]
  36.  
  37. # 定时任务配置
  38. beat_schedule = {
  39. 'test1': {
  40. # 具体需要执行的函数
  41. # 该函数必须要使用@app.task装饰
  42. 'task': 'celery_tasks.test1_run',
  43. # 定时时间
  44. # 每分钟执行一次,不能为小数
  45. 'schedule': crontab(minute='*/1'),
  46. # 或者这么写,每小时执行一次
  47. # "schedule": crontab(minute=0, hour="*/1")
  48. # 执行的函数需要的参数
  49. 'args': ()
  50. },
  51. 'test2': {
  52. 'task': 'celery_tasks.test2_run',
  53. # 设置定时的时间,10秒一次
  54. 'schedule': timedelta(seconds=10),
  55. 'args': ()
  56. }}

celery_workder.py # 主文件

  1. from __future__ import absolute_import
  2.  
  3. # 拒绝隐式引入,如果celery.py和celery模块名字一样,避免冲突,需要加上这条语句
  4. # 该代码中,名字是不一样的,最好也要不一样
  5. # celery test -- worker
  6.  
  7. from celery import Celery
  8.  
  9. def create_worker():
  10. # app = Celery('tasks', broker=di)
  11. '''app = Celery('tasks',
  12. #backend=di_backend,
  13. broker=di_broker,
  14. include=['celery_tasks'])
  15. '''
  16. app = Celery()
  17. #app.conf.update(result_expires=3600,)
  18. app.config_from_object('celery_config')
  19. return app
  20.  
  21. app = create_worker()

celery_tasks.py # task方法文件

  1.  
  2. from celery_worker import app
  3. from celery.task import Task
  4. import time
  5.  
  6. # tasks.py
  7. class MyTask(Task):
  8. def on_success(self, retval, task_id, args, kwargs):
  9. print('task done: {0}'.format(retval))
  10. return super(MyTask, self).on_success(retval, task_id, args, kwargs)
  11.  
  12. def on_failure(self, exc, task_id, args, kwargs, einfo):
  13. print('task fail, reason: {0}'.format(exc))
  14. return super(MyTask, self).on_failure(exc, task_id, args, kwargs, einfo)
  15.  
  16. @app.task(base=MyTask)
  17. def add(x, y):
  18. #raise KeyError
  19. print('wwww')
  20. return x + y
  21.  
  22. @app.task
  23. def mul(x, y):
  24. return x * y
  25.  
  26. @app.task
  27. def xsum(numbers):
  28. return sum(numbers)
  29.  
  30. @app.task
  31. def test(arg):
  32. print(arg)
  33.  
  34. def test11():
  35. time.sleep(1)
  36. print('test11')
  37.  
  38. # ....略

运行-发布任务

celery -A celery_worker beat

运行-执行任务

celery -A celery_worker -l info -P eventlet

3.2.2 装饰器添加任务-动态添加

在上一章节中给出的案例是在配置文件中写入参数beat_schedule;

有时这样不太方便,需要更灵活的添加定时任务;

  1. def setup_periodic_tasks(sender, **kwargs):
  2. # 每5s调用 test('hello')
  3. sender.add_periodic_task(5.0, test.s('hello'), name='add every 5')
  4.  
  5. # 每20s调用 test('world')
  6. sender.add_periodic_task(10.0, test.s('world'), expires=7)
  7.  
  8. # 每周一早上7:30 执行 test('Happy Mondays!')
  9. sender.add_periodic_task(
  10. crontab(hour=7, minute=30, day_of_week=1), # 可灵活修改
  11. test.s('Happy Mondays!'),
  12. )
  13.  
  14. setup_periodic_tasks(app)
  15. print('定时任务列表', app.conf.beat_schedule)

执行命令celery -A celery_test beat -l debug

可以比较一下定时任务列表的输出。

没有添加任务:

  1. (vir_venv) E:\python\code_2>celery -A celery_test beat -l debug
  2. 定时任务列表 {}
  3. celery beat v4.3.0 (rhubarb) is starting.

添加任务之后:

  1. (vir_venv) E:\python\code_2>celery -A celery_test beat -l debug
  2. 定时任务列表 # 已格式化
  3. {
  4. "add every 5": {
  5. "schedule": 5.0,
  6. "task": "celery_tasks.test",
  7. "args": [
  8. "hello"
  9. ],
  10. "kwargs": {},
  11. "options": {}
  12. },
  13. "celery_tasks.test('world')": {
  14. "schedule": 10.0,
  15. "task": "celery_tasks.test",
  16. "args": [
  17. "world"
  18. ],
  19. "kwargs": {},
  20. "options": {
  21. "expires": 7
  22. }
  23. },
  24. "celery_tasks.test('Happy Mondays!')": {
  25. "schedule": "",
  26. "task": "celery_tasks.test",
  27. "args": [
  28. "HappyMondays!"
  29. ],
  30. "kwargs": {},
  31. "options": {}
  32. }
  33. }

相关启动命令:

celery -A celery_worker worker -l info -P eventlet --logfile=c.log

celery -A celery_test beat -l debug

4. celery相关命令

发布任务

celery -A celery_task beat

执行任务

celery -A celery_task worker -l info -P eventlet

后台启动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

5. 指定时间格式

复杂的定时功能可以使用crontab功能,它跟linux自带的crontab所支持的格式是一样的,非常方便定制任务执行时间。

  1. from celery.schedules import crontab
  2.  
  3. app.conf.beat_schedule = {
  4. # Executes every Monday morning at 7:30 a.m.
  5. 'add-every-monday-morning': {
  6. 'task': 'tasks.add',
  7. 'schedule': crontab(hour=7, minute=30, day_of_week=1),
  8. 'args': (16, 16),
  9. },
  10. }

上面的案例是在每个周一的7:30执行tasks.add任务。

celery task - 2的更多相关文章

  1. 分布式任务队列 Celery —— Task对象

    转载至 JmilkFan_范桂飓:http://blog.csdn.net/jmilk  目录 目录 前文列表 前言 Task 的实例化 任务的名字 任务的绑定 任务的重试 任务的请求上下文 任务的继 ...

  2. celery task异步任务

    业务端后台:通过python manage运行 运行用例时,用python manage运行时会卡,影响效率 celery task 本身自己也是个服务,异步处理case 异步:小明去给我买个东西,我 ...

  3. Celery Task(定时任务)及参数

    celery beat 是一个调度器:它以常规的时间间隔开启任务,任务将会在集群中的可用节点上运行. 默认情况下,入口项是从 beat_schedule 设置中获取,但是自定义的存储也可以使用,例如在 ...

  4. Celery 源码解析三: Task 对象的实现

    Task 的实现在 Celery 中你会发现有两处,一处位于 celery/app/task.py,这是第一个:第二个位于 celery/task/base.py 中,这是第二个.他们之间是有关系的, ...

  5. celery 停止执行中 task

    目录 原因 解决过程 原因 因为最近项目需求中需要提供对异步执行任务终止的功能,所以在寻找停止celery task任务的方法.这种需求以前没有碰到过,所以,只能求助于百度和google,但是找遍了资 ...

  6. 分布式任务队列 Celery —— 深入 Task

    目录 目录 前文列表 前言 Task 的实例化 任务的名字 任务的绑定 任务的重试 任务的请求上下文 任务的继承 前文列表 分布式任务队列 Celery 分布式任务队列 Celery -- 详解工作流 ...

  7. [源码解析] 并行分布式任务队列 Celery 之 Task是什么

    [源码解析] 并行分布式任务队列 Celery 之 Task是什么 目录 [源码解析] 并行分布式任务队列 Celery 之 Task是什么 0x00 摘要 0x01 思考出发点 0x02 示例代码 ...

  8. celery kill task

    from celery.task.control import revokerevoke(task_id, terminate=True) https://stackoverflow.com/ques ...

  9. 异步任务队列Celery在Django中的使用

    前段时间在Django Web平台开发中,碰到一些请求执行的任务时间较长(几分钟),为了加快用户的响应时间,因此决定采用异步任务的方式在后台执行这些任务.在同事的指引下接触了Celery这个异步任务队 ...

随机推荐

  1. ASP.NET MVC4中对JS和CSS的引用

    https://www.cnblogs.com/madyina/p/3702314.html ASP.NET MVC4中对JS和CSS的引用又做了一次变化,在MVC3中我们这样引用资源文件: < ...

  2. yolov3 讲解

    参考博客:https://blog.csdn.net/litt1e/article/details/88907542

  3. 【Python】获取星期字符串

    原理:字符串切片 1.0代码: #获取星期字符串 weekStr="星期一星期二星期三星期四星期五星期六星期日" weekId=eval(input("请输入星期数字(1 ...

  4. ORA-00904: "I_LEVEL": invalid identifier

    问题描述 ORA-00904: "I_LEVEL": invalid identifier 标示符无效

  5. SSM-整合简单配置

    首先说明Spring和Mybatis的版本: Spring:3.2.4 Mybatis:3.3.0 使用了C3P0连接池和Log4J日志,下面是jar包总览: 然后是项目目录总览: 为了能够让项目跑一 ...

  6. Android SDK安装环境变量配置

    安卓tool: http://tools.android-studio.org/ SDK下载地址:http://dl.google.com/android/android-sdk_r24.4.1-wi ...

  7. pycharm连接mysql5.7

    由于加密方式改变 需要在url后增加 ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC

  8. Java-POJ1003-Hangover

    题目大意: 给出一个浮点数a,求出使得 不等式 1/2 + 1/3 + ... + 1/(n+1) ≥ a 成立的最小值 大水题,由于数据范围小,给出了确认上界5.20,满足二分答案 但是我懒啊,直接 ...

  9. STM32F103之ADC学习记录

    1.问题 1)10位ADC的误差是多少? 首先要分清分辨率与精度的区别. 10cm的尺子,有100个等分刻度,则该尺子的分辨率为1mm. 但不能说这把尺子的精度是1mm. 在冬天,尺子会热胀冷缩,依然 ...

  10. 题解【洛谷P1938】 [USACO09NOV]找工就业Job Hunt

    题面 题解 将路径连边\((x, y, d)\) ,将航线连边\((x, y, d - w)\).其中线路是从\(x\)到\(y\),航线的费用为\(w\),\(d\)的含义如题面. 跑一遍\(SPF ...