一、简介
Celery是基于分布式消息传递的开源异步任务队列。它侧重实时操作,也可用于计划任务。它的执行组件叫tasks,可在一个或多个worker节点上进行并行运算,支持的方式有multiprocessing,eventlet以及gevent。tasks可异步运行也可通过wait(),ready()同步运行。
消息broker推荐RabbitMQ,也可以是Redis,Beanstalk,MongoDB,CouchDB,关系型数据库(通过SQLAlchemy或Django ORM)。
二、总体架构
Broker(RabbitMQ)将tasks发送到各个worker节点。worker节点是一组联网的电脑运行着一个或多个Celeryd实例。woker节点可根据负载情况部署。
三、特性
四、实战 (演示级代码)
1、安装celery
$ pip install celery
或者
$ easy_install celery
2、安装RabbitMQ
go to here
3、安装mongodb,配置
go to here
4、服务器设置
服务器A:192.168.1.102, consumer,(worker server),安装mongodb,pymongo,RabbitMQ,Celery
服务器B:192.168.1.104, producer,安装pymongo,Celery
我们要做的是在服务器A上编写具体的任务,服务器B调用服务器A的任务
5、服务器A代码
celeryconfig.py:
CELERY_IMPORTS = ("Tasks.user","tasks.test",)
BROKER_HOST = "192.168.1.102"
BROKER_PORT = 5672 #默认的端口
BROKER_USER = 'sns' #rabbitmq的配置参考相关文章
BROKER_PASSWORD = "sns"
BROKER_VHOST = "sns_host"
CELERY_RESULT_BACKEND = "mongodb"
CELERY_MONGODB_BACKEND_SETTINGS = {
'host':'192.168.1.102',
'port':27017,
'database':'sns_mq',
'taskmeta_collection':"sns_taskmeta_collection",
}
CELERY_QUEUES = {"user":{
"exchange":"user",
"exchange_type":"direct",
"binding_key":"user"
},
"other":{
"exchange":"other",
"exchange_type":"direct",
"binding_key":"other",
}
}
CELERY_ROUTES = {
" Tasks.user ":{
"queue":"user",
"routing_key":"user"
},
" Tasks. test":
{
"queue":"other",
"routing_key":"other"
}
}
Tasks/user.py:
from celery.task import task
from mongoengine import *
'''
注意:
任务定义可以是通过task装饰的函数也可以是继承至Task的类。
任务实例化只进行一次,实例化完成后将被注册到全局任务表,
也就是说当任务是Python类时,每个进程中类的__init__构造函数
只执行一次,从语义上而言任务类更接近于Actor。这个特点可用于
缓存各种资源,比如数据库连接。
task装饰器可以有多个参数,这些参数对应于Task类的类成员变量,
比如任务的重试次数,重试handler都可在Task子类中重载。因此在生产
环境中的多数任务推荐用类的方式。具体细节可参考官方文档。
http://ask.github.com/celery/userguide/tasks.html
演示代码简便起见用函数的形式。
'''
connect('Proj',host='192.168.1.102',port=27017,max_pool_size=20)
from Proj.sns_users.docs import UserCache
@task
def get_all_record():
return list(UserCache.objects.all())
在celeryconfig.py所在目录下运行celeryd -l INFO -Q user, other
celeryd的守护进程运行方式脚本可参考官方文档
6、服务器B
celeryconfig.py
BROKER_HOST = "192.168.1.102"
BROKER_PORT = 5672
BROKER_USER = 'sns'
BROKER_PASSWORD = "sns"
BROKER_VHOST = "sns_host"
CELERY_RESULT_BACKEND = "mongodb"
CELERY_MONGODB_BACKEND_SETTINGS = {
'host':'192.168.1.102',
'port':27017,
'database':'sns_mq',
'taskmeta_collection':"sns_taskmeta_collection",
}
在celeryconfig.py所在目录下运行python
>> from celery.execute import send_task
>>r = send_task("Task.user.get_all_record",routing_key = 'user', queue='user')
>>r.ready()
True
>>r.result
...
五、一些说法
Celery 不是“只支持Python“,它采用Workhook的形式和其他语言、平台进行协作 —— 个人观点这比gearman的多语言支持方法更好。Celery其实只是一个协议,celeryd恰巧是python写的~,仅次而已。、
六 、celery中的Map/Reduce
从某种程度上而言,Celery是支持Map/Reduce的,对应的celery功能称为Tasksets和Chords。比如:
任务:task.py
Celery是基于分布式消息传递的开源异步任务队列。它侧重实时操作,也可用于计划任务。它的执行组件叫tasks,可在一个或多个worker节点上进行并行运算,支持的方式有multiprocessing,eventlet以及gevent。tasks可异步运行也可通过wait(),ready()同步运行。
消息broker推荐RabbitMQ,也可以是Redis,Beanstalk,MongoDB,CouchDB,关系型数据库(通过SQLAlchemy或Django ORM)。
二、总体架构
三、特性
消息机制 | 支持 RabbitMQ, Redis, Beanstalk, MongoDB, CouchDB, 以及 SQL 数据库. |
容错 | 与 RabbitMQ配合可完美实现错误恢复 |
分布式 | 运行于一台或多台服务器。支持Broker群集和HA,可任意添加worker而无需在服务器中心节点配置。 |
并发 | 通过Python的multiprocessing, Eventlet, gevent 或者他们的混合实现并发执行. |
Scheduling | 支持cron类的递归式任务,或者指定时间、倒数等任务执行方式. |
延迟 | 极低延迟. |
返回值 | 任务运行结果可储存在指定的结果存储后台,你可以等待结果或忽略运算结果 |
返回值存储 | 支持SQL数据库, MongoDB, Redis, Tokyo Tyrant, Cassandra, 或 AMQP (消息通知). |
Webhooks | 用户跨语言/平台任务分配。 |
Rate limiting | Supports rate limiting by using the token bucket algorithm, which accounts for bursts of traffic. Rate limits can be set for each task type, or globally for all. |
消息路由 | 通过AMQP灵活的路由模型你可以将任务路由到任意worker服务器,可配置或运行时指定。 |
远程控制 | 可通过广播消息远程控制worker节点。Celery内置了大量的相关命令,也可以轻松实现自定义命令(只适用AMQP和Redis) |
监控 | 可实时获得workers的一切信息 |
对象序列化 | 支持 Pickle, JSON, YAML,或自定义序列化程序. |
错误追踪 | |
UUID | 每个任务都有一个UUID用于查询该任务的运行状态以及返回值。 |
出错重试 | 当任务执行失败时可根据配置重试。配置内容包括最大重试次数,重试时间间隔。 |
任务集 | 任务集由多个子任务构成,可以获得子任务的数量,执行情况,以及各个子任务的运算结果。 |
Made for Web | 可通过Ajax查询任务运行状态和运行结果。 |
出错通知 | 当任务出错是可通过邮件通知管理员 |
四、实战 (演示级代码)
1、安装celery
$ pip install celery
或者
$ easy_install celery
2、安装RabbitMQ
go to here
3、安装mongodb,配置
go to here
4、服务器设置
服务器A:192.168.1.102, consumer,(worker server),安装mongodb,pymongo,RabbitMQ,Celery
服务器B:192.168.1.104, producer,安装pymongo,Celery
我们要做的是在服务器A上编写具体的任务,服务器B调用服务器A的任务
5、服务器A代码
celeryconfig.py:
CELERY_IMPORTS = ("Tasks.user","tasks.test",)
BROKER_HOST = "192.168.1.102"
BROKER_PORT = 5672 #默认的端口
BROKER_USER = 'sns' #rabbitmq的配置参考相关文章
BROKER_PASSWORD = "sns"
BROKER_VHOST = "sns_host"
CELERY_RESULT_BACKEND = "mongodb"
CELERY_MONGODB_BACKEND_SETTINGS = {
'host':'192.168.1.102',
'port':27017,
'database':'sns_mq',
'taskmeta_collection':"sns_taskmeta_collection",
}
CELERY_QUEUES = {"user":{
"exchange":"user",
"exchange_type":"direct",
"binding_key":"user"
},
"other":{
"exchange":"other",
"exchange_type":"direct",
"binding_key":"other",
}
}
CELERY_ROUTES = {
" Tasks.user ":{
"queue":"user",
"routing_key":"user"
},
" Tasks. test":
{
"queue":"other",
"routing_key":"other"
}
}
Tasks/user.py:
from celery.task import task
from mongoengine import *
'''
注意:
任务定义可以是通过task装饰的函数也可以是继承至Task的类。
任务实例化只进行一次,实例化完成后将被注册到全局任务表,
也就是说当任务是Python类时,每个进程中类的__init__构造函数
只执行一次,从语义上而言任务类更接近于Actor。这个特点可用于
缓存各种资源,比如数据库连接。
task装饰器可以有多个参数,这些参数对应于Task类的类成员变量,
比如任务的重试次数,重试handler都可在Task子类中重载。因此在生产
环境中的多数任务推荐用类的方式。具体细节可参考官方文档。
http://ask.github.com/celery/userguide/tasks.html
演示代码简便起见用函数的形式。
'''
connect('Proj',host='192.168.1.102',port=27017,max_pool_size=20)
from Proj.sns_users.docs import UserCache
@task
def get_all_record():
return list(UserCache.objects.all())
在celeryconfig.py所在目录下运行celeryd -l INFO -Q user, other
celeryd的守护进程运行方式脚本可参考官方文档
6、服务器B
celeryconfig.py
BROKER_HOST = "192.168.1.102"
BROKER_PORT = 5672
BROKER_USER = 'sns'
BROKER_PASSWORD = "sns"
BROKER_VHOST = "sns_host"
CELERY_RESULT_BACKEND = "mongodb"
CELERY_MONGODB_BACKEND_SETTINGS = {
'host':'192.168.1.102',
'port':27017,
'database':'sns_mq',
'taskmeta_collection':"sns_taskmeta_collection",
}
在celeryconfig.py所在目录下运行python
>> from celery.execute import send_task
>>r = send_task("Task.user.get_all_record",routing_key = 'user', queue='user')
>>r.ready()
True
>>r.result
...
五、一些说法
Celery 不是“只支持Python“,它采用Workhook的形式和其他语言、平台进行协作 —— 个人观点这比gearman的多语言支持方法更好。Celery其实只是一个协议,celeryd恰巧是python写的~,仅次而已。、
六 、celery中的Map/Reduce
从某种程度上而言,Celery是支持Map/Reduce的,对应的celery功能称为Tasksets和Chords。比如:
任务:task.py
from celery.task import task @task def add(x, y): return x + y @task def tsum(numbers): return sum(numbers) 可以用以下方法实现map/reduce: >>> from celery.task import chord >>> from tasks import add, tsum >>> chord(add.subtask((i, i)) ... for i in xrange(100))(tsum.subtask()).get() 9900 当然由于同步和消息传递上的开销这段代码的效率没有 sum(i + i for i in xrange(100)) 高。同步是一种非常耗时的工作(chord等待所有任务的完成),因此如果不是特别必要应该尽量减少chords的使用。 当然,在多数并行计算算法中同步又不必不可少的。 默认情况下,同步是这样实现的:chord每秒都在不断taskset的完成状况,当taskset完成后调用callback子任务。