Celery (1)- 安装配置及使用

15 篇文章 0 订阅
5 篇文章 1 订阅

简介

  • Celery是一个简单的/灵活且可靠的,处理大量消息的分布式系统
  • 专注于实时处理的异步任务队列
  • 同时也支持任务调度

架构图

celery架构图

组件介绍

  • Producer : 任务生产者. 调用 Celery API , 函数或者装饰器, 而产生任务并交给任务队列处理的都是任务生产者。

  • Broker : 消息代理, 队列本身. 也称为消息中间件. 接受任务生产者发送过来的任务消息, 存进队列再按序分发给任务消费方(通常是消息队列或者数据库). 通常用 RabbitMQ或者Redis

  • Celery Beat : 任务调度器. Beat 进程会读取配置文件的内容, 周期性的将配置中到期需要执行的任务发送给任务队列.例如如下配置的一个周期性执行的一个任务:

    CELERYBEAT_SCHEDULE = {
        'send_mail': {
            'task': 'work.notify.email.send_mail',
            # 'schedule': timedelta(minute=1),
            'schedule': crontab(minute='*/1'),
            'args': ('usr', 'sub', 'msg')
        }
    }
    

    任务调度主要是为了解决业务场景中定时或周期任务,分别使用timedelta和crontab来定义计划任务,crontab的精度无法精确到秒时可使用timedelta代替,CELERYBEAT_SCHEDULE下可以定义多个计划/周期任务,send_mail为任务名称,task为任务单元导入名,schedule为具体调度,args为任务单元的参数.

    运行时可先启动work进程池(celery worker -A work.app -l info)然后再启动beat进程池(celery beat -A work.app -l info),观察会发现beat进程每分钟生成一个任务,work进程发现任务后立即执行

  • Celery Worker : 执行任务的消费者, 通常会在多台服务器运行多个消费者, 提高运行效率.

  • Result Backend : 任务处理完成之后保存状态信息和结果, 以供查询.

依赖库
  • billiard : 基于 Python2.7 的 multisuprocessing 而改进的库, 主要用来提高性能和稳定性
  • librabbitmp : C 语言实现的 Python 客户端,
  • kombu : Celery 自带的用来收发消息的库, 提供了符合 Python 语言习惯的, 使用 AMQP 协议的高级借口.
消息代理

使用于生产环境的消息代理有 RabbitMQ 和 Redis, 官方推荐 RabbitMQ.

使用场景

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

序列化

方案说明
picklepickle 是Python 标准库中的一个模块, 支持 Pyuthon 内置的数据结构, 但他是 Python 的专有协议. Celery 官方不推荐.
sonjson 支持多种语言, 可用于跨语言方案.
yamlyaml 表达能力更强, 支持的数据类型较 json 多, 但是 python 客户端的性能不如 json
msgpack二进制的类 json 序列化方案, 但比 json 的数据结构更小, 更快.

配置文件参数说明

配置项说明
CELERY_DEFAULT_QUEUE默认队列
CELERY_BROKER_URLBroker 地址
CELERY_RESULT_BACKEND结果存储地址
CELERY_TASK_SERIALIZER任务序列化方式
CELERY_RESULT_SERIALIZER任务执行结果序列化方式
CELERY_TASK_RESULT_EXPIRES任务过期时间
CELERY_ACCEPT_CONTENT指定任务接受的内容类型(序列化)

代码示例:

# 安装
$ pip install celery, redis, msgpack
 
# 配置文件 celeryconfig.py
 
    CELERY_BROKER_URL = 'redis://localhost:6379/1'
    CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
    CELERY_TASK_SERIALIZER = 'json'
    CELERY_RESULT_SERIALIZER = 'json'
    CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24   # 任务过期时间
    CELERY_ACCEPT_CONTENT = ["json"]            # 指定任务接受的内容类型.
 
# 初始化文件 celery.py
    
    from __future__ import absolute_import
    from celery import Celery
 
    app = Celery('proj', include=["proj.tasks"])
    app.config_from_object("proj.celeryconfig")
 
    if __name__ == "__main__":
        app.start()     
 
# 任务文件 tasks.py
 
    from __future__ import absolute_import
    from proj.celery import app
 
    @app.task
    def add(x, y):
        return x + y    
 
# 启动消费者
    $ celery -A proj worker -l info
 
# 在终端中测试
    > from proj.tasks import add
    > r = add.delay(2,4)
    > r.result
      6
    > r.status
      u"SUCCESS"
    > r.successful()
      True
 
    > r.ready()     # 返回布尔值,  任务执行完成, 返回 True, 否则返回 False.
    > r.wait()      # 等待任务完成, 返回任务执行结果.
    > r.get()       # 获取任务执行结果
    > r.result      # 任务执行结果.
    > r.state       # PENDING, START, SUCCESS
    > r.status      # PENDING, START, SUCCESS
 
    # 使用 AsyncResult 方式获取执行结果.
    # AsyncResult 主要用来存储任务执行信息与执行结果(类似 js 中的 Promise 对象), 
    > from celery.result import AsyncResult
    > AsyncResult(task_id).get()
      4

任务调度的方法

  • delay

    task.delay(args1, args2, kwargs=value_1, kwargs2=value_2)
    
  • apply_async
    delay 实际上是 apply_async 的别名, 还可以使用如下方法调用, 但是 apply_async 支持更多的参数:

    task.apply_async(args=[arg1, arg2], kwargs={key:value, key:value})
    

    支持的参数

    • countdown : 等待一段时间再执行.

      add.apply_async((2,3), countdown=5)
      
    • eta : 定义任务的开始时间

      add.apply_async((2,3), eta=now+tiedelta(second=10))
      
    • expires : 设置超时时间.

      add.apply_async((2,3), expires=60)
      
    • retry : 定时如果任务失败后, 是否重试.

      add.apply_async((2,3), retry=False)
      
    • retry_policy : 重试策略.

      • max_retries : 最大重试次数, 默认为 3 次.
      • interval_start : 重试等待的时间间隔秒数, 默认为 0 , 表示直接重试不等待.
      • interval_step : 每次重试让重试间隔增加的秒数, 可以是数字或浮点数, 默认为 0.2
      • interval_max : 重试间隔最大的秒数, 即 通过 interval_step 增大到多少秒之后, 就不在增加了, 可以是数字或者浮点数, 默认为 0.2

    自定义发布者,交换机,路由键, 队列, 优先级,序列方案和压缩方法:

    task.apply_async((2,2), compression='zlib',
        serialize='json',
        queue='priority.high',
        routing_key='web.add',
        priority=0,
        exchange='web_exchange')
    

使用任务调度

from datetime import timedelta
from celery.schedules import crontab

BORKER_URL = 'redis://127.0.0.1:6379/1'
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/2'

# 设置时区
CELERY_TIMEZONE = 'Asia/Shanghai'


# 导入指定的任务模块
CELERY_IMPORT = (
	'celery_app.task1',
	'celery_app.task2',
)

CELERYBEAT_SCHEDULE = {
	# 每隔10秒钟执行任务
	'task1':{
		'task':'celery_app.task1.add',
		'schedule':timedelta(seconds=10),
		'args':(2,8)
	},

	# 每天的19:28分执行任务
	'task2':{
		'task':'celery_app.task2.multiply',
		'schedule':crontab(hour=19,minute=28),
		'args':(4,5)
	}
}

# 使用
# Worker celery worker -A task  -l INFO     启动worker
# Beat: celery beat -A task -l INFO         启动beat
# celery -B -A task worker -l INFO         同时启动beat worker
# celery worker --help 

使用自定义调度类还可以实现动态添加任务. 使用 Django 可以通过 Django-celery 实现在管理后台创建,删除,更新任务, 是因为他使用了自定义的 调度类 djcelery.schedulers.DatabaseScheduler .

任务绑定, 记录日志, 重试

# 修改 tasks.py 文件.
 
from celery.utils.log import get_task_logger
logger = get_task_logger(__name__)
 
@app.task(bind=True)
def div(self, x, y):
    logger.info(('Executing task id {0.id}, args: {0.args!r}'
                 'kwargs: {0.kwargs!r}').format(self.request))
    try:
        result = x/y
    except ZeroDivisionError as e:
        raise self.retry(exc=e, countdown=5, max_retries=3)     # 发生 ZeroDivisionError 错误时, 每 5s 重试一次, 最多重试 3 次.
 
    return result

当使用 bind=True 参数之后, 函数的参数发生变化, 多出了参数 self, 这这相当于把 div 编程了一个已绑定的方法, 通过 self 可以获得任务的上下文.

信号系统

信号可以帮助我们了解任务执行情况, 分析任务运行的瓶颈. Celery 支持 7 种信号类型.

  1. 任务信号

    • before_task_publish : 任务发布前
    • after_task_publish : 任务发布后
    • task_prerun : 任务执行前
    • task_postrun : 任务执行后
    • task_retry : 任务重试时
    • task_success : 任务成功时
    • task_failure : 任务失败时
    • task_revoked : 任务被撤销或终止时
  2. 应用信号

  3. Worker 信号

  4. Beat 信号

  5. Eventlet 信号

  6. 日志信号

  7. 命令信号

不同的信号参数格式不同, 具体格式参见官方文档

# 在执行任务 add 之后, 打印一些信息.
@after_task_publish
def task_send_handler(sender=None, body=None, **kwargs):
    print 'after_task_publish: task_id: {body[id]}; sender: {sender}'.format(body=body, sender=sender)

根据任务状态执行不同操作

# tasks.py
class MyTask(Task):
 
    def on_success(self, retval, task_id, args, kwargs):
        print 'task done: {0}'.format(retval)
        return super(MyTask, self).on_success(retval, task_id, args, kwargs)
 
    def on_failure(self, exc, task_id, args, kwargs, einfo):
        print 'task fail, reason: {0}'.format(exc)
        return super(MyTask, self).on_failure(exc, task_id, args, kwargs, einfo)
 
# 正确函数, 执行 MyTask.on_success() :
@app.task(base=MyTask)
def add(x, y):
    return x + y
 
# 错误函数, 执行 MyTask.on_failure() : 
@app.task  #普通函数装饰为 celery task
def add(x, y):
    raise KeyError
    return x + y

Flower web 监控工具

  • 查看任务历史,任务具体参数,开始时间等信息;
  • 提供图表和统计数据
  • 实现全面的远程控制功能, 包括但不限于 撤销/终止任务, 关闭重启 worker, 查看正在运行任务
  • 提供一个 HTTP API , 方便集成.

Flower 的 supervisor 管理配置文件:

[program:flower]
command=/opt/PyProjects/venv/bin/flower -A celery_worker:celery --broker="redis://localhost:6379/2" --address=0.0.0.0 --port=5555 
directory=/opt/PyProjects/app
autostart=true
autorestart=true
startretries=3 
user=derby
stdout_logfile=/var/logs/%(program_name)s.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=30
stderr_logfile=/var/logs/%(program_name)s-error.log
stderr_logfile_maxbytes=50MB
stderr_logfile_backups=3
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Django-Celery是一个用于在Django应用中集成Celery任务队列的插件。它允许你将耗时的任务异步执行,从而提高应用的性能和响应速度。下面是一些使用Django-Celery的步骤: 1. 安装Celery和Django-Celery:首先,确保你已经安装Celery和Django-Celery。你可以通过运行以下命令来安装它们: ``` pip install celery django-celery ``` 2. 配置Celery:在Django项目的`settings.py`文件中,添加以下配置: ```python # settings.py # 配置Celery Broker(消息代理) BROKER_URL = 'amqp://guest:guest@localhost:5672//' # 配置Celery Backend(结果存储) CELERY_RESULT_BACKEND = 'db+sqlite:///results.sqlite' # 配置Celery Beat(定时任务) CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers.DatabaseScheduler' ``` 请根据你的实际情况修改上述配置。 3. 创建Celery App:在你的Django项目中,创建一个名为`celery.py`的文件,并添加以下代码: ```python # celery.py from celery import Celery app = Celery('your_project_name') # 配置Celery app.config_from_object('django.conf:settings', namespace='CELERY') # 自动从Django app中加载任务 app.autodiscover_tasks() ``` 确保将`your_project_name`替换为你的项目名称。 4. 创建任务:在Django app中创建一个任务。例如,你可以在你的app目录下创建一个名为`tasks.py`的文件,并添加以下代码: ```python # tasks.py from celery import shared_task @shared_task def add(x, y): return x + y ``` 这是一个简单的任务示例,将两个数字相加并返回结果。 5. 启动Celery Worker:运行以下命令来启动Celery worker: ``` celery -A your_project_name worker --loglevel=info ``` 确保将`your_project_name`替换为你的项目名称。 6. 调用任务:在你的Django应用程序中,你可以通过导入任务函数并调用它来触发任务的执行。例如: ```python from your_app.tasks import add result = add.delay(1, 2) ``` 这里使用了`delay()`方法来异步调用任务。你也可以使用`apply_async()`方法来更精确地控制任务的执行。 这些是使用Django-Celery的基本步骤。你还可以配置更多高级选项,如任务重试、任务结果存储等。请参考Django-Celery的官方文档以获取更多详细信息。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值