任务调度利器:Celery

Celery简要介绍

CeleryPython开发的分布式任务调度模块,是一个异步的任务队列基于分布式消息传递Celery本身不含消息服务,它使用第三方消息服务来传递任务,目前,Celery支持的消息服务有RabbitMQRedis甚至是数据库,当然Redis应该是最佳选择。

使用Redis作为Broker时,再安装一个celery-with-redis

 

celery(芹菜)是一个异步任务队列/基于分布式消息传递的作业队列。

它侧重于实时操作,但对调度支持也很好。

celery用于生产系统每天处理数以百万计的任务。

celery是用Python编写的,但该协议可以在任何语言实现。它也可以用其他语言通过webhooks实现。

目前已知有php/ruby/nodejs的实现

为什么用Celery?

异步

耗时久的事儿可以扔给 Worker处理,处理完可以触发子任务提醒

天然的并发能力(多进程/协程)!

非常方便添加 Worker来增强处理能力

Celery提供了Web方式的监控/报警,这样,我们就可以监控每个任务的情况了

出现错误可以自动处理/重试

角色介绍

Brokers: 提供队列服务,Celery支持的Brokers:

RabbitMQ(推荐)

Redis

MongoDB

Beanstalk

CouchDB

SQLAlchemy(MySQL/PostgreSQL/Sqlite/Oracle)

Amazon SQS

Worker: 真正干活的,实际运行任务的节点

开始 Celery 的第一步

选择Broker

在你正式开始使用 Celery之前,你需要选择、安装并运行一个 broker

Broker 是一种负责接收、发送任务消息(task messages)的服务

你可以从以下几种 broker中选择一个:

RabbitMQ :[[http://www.rabbitmq.com/]]

功能完整、安全、饱经实践检验的 broker。如果对你而言,不丢失消息非常重要,RabbitMQ将是你最好的选择。

请查看 [[/技术分享/Celery/broker-installation]]以便获得更多关于 RabbitMQ安装和配置相关的信息。

 

Redis :[[http://redis.io/]]

也是一个功能完整的 broker,但电源故障或异常将导致数据丢失。

请查看 [[/技术分享/Celery/otherqueues-redis]]以便配置相关的信息。

数据库

不推荐使用数据库作为消息队列,但在非常小的应用中可以使用。Celery可以使用 SQLAlchemy DjangoORMS。请查看 [[/技术分享/Celery/otherqueues-sqlalchemy]] [[/技术分享/Celery/otherqueues-django]]

更多其他选择

除了上面列出的以外,还有其他可以选择的传输实现,例如 CouchDB,Beanstalk, MongoDB, and SQS。请查阅 Kombu的文档以便获得更多信息。

创建一个简单“任务”(Task)

from celery import Celery

app = Celery(
    'myapp',
    broker='amqp://guest@localhost//',
    #broker='redis://localhost:6379/0',
    # ## add result backend here ifneeded.
   
backend='amqp',
)


@app.task
def add(x, y):
    return x + y

运行 worker 服务器

celery -A tasks worker --loglevel=info

执行任务(task)

 

>>> result = add.delay(4, 4)

这里是一些你可以如何处理结果的方法:

>>> result.ready() # 任务是否已经执行,如果已经执行完毕,返回值为 TrueFalse
>>> result.result # 任务还没完成,尚无返回值。None
>>> result.get() # 等待,直到任务执行完毕并返回值。8
>>> result.result # 直接返回结果,不产生任何错误。8
>>> result.successful() # 任务是否成功执行,如果成功则返回值 TrueTrue

 

CELERY_RESULT_BACKEND ="amqp"#: 我们希望结果最多保存 5 分钟。 #: 注意,这个特性需要 2.1.1 以上版本 RabbitMQ 才能支持。#: 如果你使用的是早期版本的 RabbitMQ,请注释下面这行。
CELERY_TASK_RESULT_EXPIRES =300
BROKER_URL = "amqp:''guest:guest@localhost :5672''" #连接 broker
CELERY_RESULT_BACKEND = "amqp" #用于存储元数据(metadata)和返回值(return values)的后端
CELERY_IMPORTS = ("tasks", ) #列出 worker 需要 import 的模块

 

使用Redis作为Broker时,再安装一个celery-with-redis

开始编写tasks.py

# tasks.py
import time
from celery import Celery
 
celery = Celery('tasks', broker='redis://localhost:6379/0')
 
@celery.task
defsendmail(mail):
    print('sending mail to %s...' % mail['to'])
    time.sleep(2.0)
    print('mail sent.')

然后启动Celery处理任务:

$ celery -A tasks worker --loglevel=info

上面的命令行实际上启动的是Worker,如果要放到后台运行,可以扔给supervisor

如何发送任务?非常简单:

>>> from tasks import sendmail
>>> sendmail.delay(dict(to='celery@python.org'))
<AsyncResult: 1a0a9262-7858-4192-9981-b7bf0ea7483b>

可以看到,CeleryAPI设计真的非常简单。

然后,在Worker里就可以看到任务处理的消息:

[2013-08-2719:20:23,363: WARNING/MainProcess] celery@MichaeliMac.local ready.
[2013-08-2719:20:23,367: INFO/MainProcess] consumer: Connected to redis://localhost:6379/0.
[2013-08-2719:20:45,618: INFO/MainProcess] Got task from broker: tasks.sendmail[1a0a9262-7858-4192-9981-b7bf0ea7483b]
[2013-08-2719:20:45,655: WARNING/PoolWorker-4] sending mail to celery@python.org...
[2013-08-2719:20:47,657: WARNING/PoolWorker-4] mail sent.
[2013-08-2719:20:47,658: INFO/MainProcess] Task tasks.sendmail[1a0a9262-7858-4192-9981-b7bf0ea7483b] succeeded in2.00266814232s: None

 

要使celery找到相应的tasks有四种方法

1 在项目的celery中写tasks。如在djproj/djproj/celery.py中直接定义task

2 使用autodiscover 但是tasks必须定义在app目录下的名字为tasks.py的文件中,如:apps/app1/tasks.py 否则找不到 ,会报KeyError错误。

3 如果不使用autodiscover,可以在项目的celery中 import 相应的module,相当于在项目的celery中写了相应的task,如在celery.py中 import apps.app2.mytasks 

4 在settings.py中设置CELERY_IMPORTS = ('apps.app2.mytasks',) 写到module级 

 

第一,假设用户正发起一个request, 并等待request完成后返回.在这一request后面的view功能中,我们可能需要执行一段花费很长时间的程序任务,这一时间可能远远大于用户能忍受的范围.当这一任务并不需要立刻执行时,我们便可以使用Celery在后台执行,而不影响用户浏览网页.当有任务需要访问远程服务器完成时,我们往往都无法确定需要花费的时间.

第二则是定期执行某些任务.比如每小时需要检查一下天气预报,然后将数据储存到数据库中.我们可以编写这一任务,然后让Celery每小时执行一次.这样我们的web应用便能获取最新的天气预报信息.

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值