我正在尝试让celery根据任务的名称来路由任务...基本上,我有名为'worker.some_name'和'web.some_name'的任务,我使用两个不同的队列,分别称为工人和网络。我希望所有工作人员的任务都转到工作队列,反之亦然。目前我有一个很大的CELERY_ROUTES字典:
CELERY_ROUTES = {
"web.some_name": {
"queue": "web"
},
"web.some_other_name": {
"queue": "web"
},
etc.... }
但我想要更通用的东西:
CELERY_ROUTES = (MyRouter(), )
class MyRouter(object):
def route_for_task(self, task, args=None, kwargs=None):
if task.split('.')[0] == "worker":
return {"queue": "worker"}
return {"queue": "web"}
但这似乎不起作用。有任何想法吗?感谢。
答案 0 :(得分:3)
你必须使用装饰器“@ app.task”来完成你在py文件中定义的任务。
您可以使用@ app.task(queue ='queue_name')
路由您的任务答案 1 :(得分:2)
您应该可以通过将交换类型从直接更改为主题来执行您想要的操作。这样,您可以将任务指定为web。*或worker。*
您可以在此处阅读:http://ask.github.com/celery/userguide/routing.html#topic-exchanges
答案 2 :(得分:1)
默认情况下,Celery 3.x不支持通配符路由,但是您可以自己实现。
以下是复制粘贴解决方案:
class TaskRouter:
def __init__(self, routes):
self.routes = {}
self.glob_routes = {}
for glob, queue in routes.items():
if '*' in glob:
self.glob_routes[glob] = queue
else:
self.routes[glob] = queue
def route_for_task(self, task, args=None, kwargs=None):
if task in self.routes:
return self.routes[task]
for route in self.glob_routes:
prefix = route.split('*')[0]
if task.startswith(prefix):
return self.glob_routes[route]
return None # for unknown tasks will be used default queue
用法:
# celery.py
CELERY_ROUTES = {
'web.*': 'web',
'web.slow_task': 'slow',
'worker.*': 'worker',
}
app = Celery('config')
app.config_from_object('django.conf:settings') # Django or your app config
app.conf.update(
CELERY_ROUTES=(TaskRouter(CELERY_ROUTES),),
)
TaskRouter的工作方式:
In [2]: CELERY_ROUTES = {
...: 'web.*': 'web',
...: 'web.slow_task': 'slow',
...: 'worker.*': 'worker',
...: }
In [3]: router = TaskRouter(CELERY_ROUTES)
In [4]: router.route_for_task('web.blabla')
Out[4]: 'web'
In [5]: router.route_for_task('web.slow_task')
Out[5]: 'slow'
In [6]: router.route_for_task('unknown_task') # None = default queue
In [7]: router.route_for_task('worker.foo')
Out[7]: 'worker'
In [8]: router.route_for_task('worker.bar')
Out[8]: 'worker'