Celery簡介
Celery 是一個簡單、靈活且可靠的,處理大量消息的分佈式系統,並且提供維護這樣一個系統的必需工具。它是一個專注於實時處理的任務隊列,同時也支持任務調度。
我們用celery處理異步job的項目中積累了一些經驗。在這裏整理一下。
。
Broker
broker在中文文檔翻譯爲中間人1。celery支持多種broker,
穩定支持的有Rabbimq和Redis,而Redis可能存在斷電時丟消息,我們選擇Rabbitmq。
import config
from celery import Celery
broker = "amqp://{user}:{password}@{host}:{port}/{vhost}".format(
user=config.get('AMQP', 'USER'),
password=config.get('AMQP', 'PASSWORD'),
host=config.get('AMQP', 'HOST'),
port=config.get('AMQP', 'PORT'),
vhost=config.get('AMQP', 'VHOST'))
celery_app = Worker('tasks',
broker=broker)
Backend
celery設計支持backend,用於存儲這些消息以及celery執行的一些消息和結果。一般情況下我們選擇Mysql作爲backend。
backend = 'db+mysql://{user}:{password}@{host}:{port}/{db}'.format(
user=config.get('MYSQL', 'USER'),
password=config.get('MYSQL', 'PASSWORD'),
host=config.get('MYSQL', 'HOST'),
port=config.get('MYSQL', 'PORT'),
db=config.get('MYSQL', 'DATABASE'))
celery_app = Worker('tasks',
broker=broker,
backend=backend)
配置隊列
celery可以配置多個Exchange,多個Queue。Exchange和Queue都是Rabbitmq中的概念。
myexchange = Exchange('myexchange', type='topic')
CELERY_QUEUES = (
Queue('defaultqueue', myexchange, routing_key="default.#"),
Queue('myqueue', myexchange, routing_key='my.#'),
Queue('testqueue', myexchange, routing_key='test.#')
)
例子中,用到一個exchange,topic類型,根據task的routing_key路由到多個queue。routing_key採用模式匹配,根據開頭字段判斷選擇queue。如果exchange爲direct類型,也能啓動服務,但是routing_key裏的#符號就不具備模式匹配特殊含義了。
CELERY_ROUTES還有另一種配置方式,只是由元組變成字典,實現的功能是類似的。
CELERY_QUEUES = {'myqueue': {'exchange': 'myexchange',
'routing_key': 'my.#'},
'testqueue': {'exchange': 'testexchange',
'routing_key': 'test.#'}}
路由
隊列影響的是celery的consumer,consumer監聽queue。路由影響producer,
CELERY_ROUTES = {'test.add': {'exchange': 'testexchange',
'routing_key': 'test.add'},
'test.del': {'exchange': 'testexchange',
'routing_key': 'test.add'},
}
producer會根據路由配置將消息發送到指定exchange,並設置routing_key。
錯誤重試
celery支持錯誤重試,可以設置重試次數,重試間隔等,非常方便。
class MyTask(Task):
max_retries = 3
default_retry_delay = 1
@celery_app.task(bind=True, name='test.del', base=MyTask)
def testdel(self, x, y):
try:
return True, x - y
except Exception as exc:
raise self.retry(exc=exc)