RPC调用多个消费者

时间:2012-09-13 13:31:51

标签: python rabbitmq messaging pika

我有一个用于侦听消息的消费者,如果消息流超过消费者可以处理的消息我想要启动此消费者的另一个实例。

但我也希望能够从消费者那里查询信息,我的想法是我可以使用RPC通过使用扇出交换来从生产者请求这些信息,所以所有生产者都获得了RPC调用

我的问题首先是可能的,其次是合理的吗?

2 个答案:

答案 0 :(得分:3)

如果问题是“是否可以将RPC消息发送到多个服务器?”答案是肯定的。

当您构建RPC调用时,您会在邮件中附加一个临时队列(通常在header.reply_to中,但您也可以使用内部消息字段)。这是RPC目标将发布其答案的队列。

当您将RPC发送到单个服务器时,您可以在临时队列上收到多条消息:这意味着可以通过以下方式形成RPC答案:

  • 来自单一来源的单条消息
  • 来自单一来源的多条消息
  • 来自多个来源的多条消息

此方案中出现的问题是

  • 你什么时候停止听?如果你知道RPC服务器的数量,你可以等到他们每个人都给你一个答案,否则你必须实现某种形式的超时
  • 您是否需要跟踪答案的来源?您可以在邮件中添加一些特殊字段以保留此信息。消息顺序也一样。

只是一些代码来展示你如何做到这一点(Python与Pika库)。请注意,这远非完美:最大的问题是你应该在得到新答案时重置超时。

    def consume_rpc(self, queue, result_len=1, callback=None, timeout=None, raise_timeout=False):
        if timeout is None:
            timeout = self.rpc_timeout

        result_list = []

        def _callback(channel, method, header, body):
            print "### Got 1/%s RPC result" %(result_len)
            msg = self.encoder.decode(body)
            result_dict = {}
            result_dict.update(msg['content']['data'])
            result_list.append(result_dict)

            if callback is not None:
                callback(msg)

            if len(result_list) == result_len:
                print "### All results are here: stopping RPC"
                channel.stop_consuming()

        def _outoftime():
            self.channel.stop_consuming()
            raise TimeoutError

        if timeout != -1:
            print "### Setting timeout %s seconds" %(timeout)
            self.conn_broker.add_timeout(timeout, _outoftime)

        self.channel.basic_consume(_callback, queue=queue, consumer_tag=queue)

        if raise_timeout is True:
            print "### Start consuming RPC with raise_timeout"
            self.channel.start_consuming()
        else:
            try:
                print "### Start consuming RPC without raise_timeout"
                self.channel.start_consuming()
            except TimeoutError:
                pass

        return result_list

答案 1 :(得分:1)

经过一番研究后,似乎无法做到这一点。如果您查看RabbitMQ.com上的教程,您会看到该调用有一个id,据我所知,它被消耗掉了。

我选择了另一种方式,即读取日志文件并聚合数据。