芹菜+反向主题交换(x-rtopic)无法正常工作

时间:2014-08-05 21:41:31

标签: python rabbitmq celery amqp librabbitmq

我正在尝试使用来自Alvaro Videla的reverse topic exchange rabbitmq plugin创建一个芹菜应用程序。工人似乎使用这种交换与经纪人联系很好但是当我主题 - 逆向路由我的任务时,不要拿起'#'或者' *',就像直接交换一样。

这就是我的队列:

Queue(name='cluster', 
          exchange = Exchange(name='cluster', 
                              type='x-rtopic',
                              delivery_mode='persistent',
                              durable=True), 
          routing_key='intel.%d.%s' % (n_cores, hostname),
          durable = True,)

现在使用以下routing_key来描述2名工作人员

  • Worker1:intel.8.host1
  • Worker2:amd.2.host2

这就是我正在尝试的任务和我所经历的任务上的routing_keys:

Routing key     | Works?   |  Result              | Expected
-------------------------------------------------------------------------
'intel'         | OK       | Nobody receives      | 
'intel.*'       | OK       | Nobody receives      |
'intel.#'       | WRONG    | Everyone receives    | just Worker1 receives
'#.host1'       | WRONG    | Everyone receives    | just Worker1 receives
'intel.*.*      | WRONG    | Everyone receives    | just Worker1 receives
'intel.*.host1  | WRONG    | Everyone receives    | just Worker1 receives
'*.2.*'         | WRONG    | Everyone receives    | just Worker2 receives
'intel.8.host1' | OK       | like direct exchange | 

为了尝试确定问题出在哪里,我已经测试了插件使用鼠兔和kombu进行简单的消息传递,并且两者都运行良好,完全符合预期。所以我认为Celery交换(路由)消息的方式一定是个问题。也许我应该创建一个自定义路由类!?

提前致谢。

1 个答案:

答案 0 :(得分:0)

经过一段时间的挖掘后,我发现Reverse主题交换插件可以与Celery一起使用。我误解了Rabbitmq Queues的工作方式。为了使其完全正常工作,我必须定义一个我的路由器,其中任务被路由到包含这些队列的交换机,并且只指定routing_key和交换机名称,这样任务仍然会循环连接到该交换机的节点和能够在任务路由密钥上使用通配符。

所以队列设置是这样的:

routed_queue ='intel.8.pchost'

CELERY_QUEUES =(

    Queue(name='cluster.%s' % routed_queue,
          exchange = Exchange(name='cluster',
                              type='x-rtopic'), 
          routing_key=routed_queue),)

路由器将是这样的:

class MyRouter(object):

def route_for_task(self, task, args=[], kwargs={}):

    routing_key = kwargs['routing_key'] if kwargs.has_key('routing_key') and\
                  kwargs['routing_key'] else '#'

    return {'exchange': 'cluster',
            'exchange_type': 'rtopic',
            'routing_key': routing_key}

然后我将routing_key作为任务的kwargs传递,能够在任务“intel。#”中设置,这意味着任务将由具有以intel开头的队列的任何工作人员执行。

唯一的问题!这是因为某些原因我不得不使用.apply_async而不是.delay来执行任务。

整个想法是能够使用群集中可用的机器规格相应地路由我的任务。某些任务应仅在intel处理器上运行,而其他任务仅在amd上运行,或者由节点中的核心数或使用主机名定义。

希望这可以帮助任何人在将来尝试做同样的事情。