RabbitMQ官网教程3——发布订阅

来源:互联网 发布:开源财务系统 php 编辑:程序博客网 时间:2024/06/06 02:02

        前面我们创建了工作队列,工作队列中每个任务只分发给一个worker。现在我们要把一个消息分发给多个消费者,这种模式就是发布订阅。为解释这种模式,我们将构建一个简单的日志系统,它包括两个程序——一个提交日志,另一个接收并打印。日志系统中每个接收程序的拷贝都会收到消息,这样可以一个将日志写入磁盘,另一个输出到屏幕。本质上讲,发布的日志消息被广播给了所有的消费者。

 

交换机

        前面的章节我们说消息发送到队列或是从队列接收消息。现在是时候介绍一下Rabbit中的消息模型了。生产者发送消息,队列存储消息,消费者接收消息。RabbitMQ中消息模型的核心是,生产者不能直接将消息发送给队列。实际上,大多数情况生产者甚至根本不知道把消息发送到哪个队列。生产者只能将消息发送到交换机。交换机很简单,一方面它从生产者接收消息,另一方面把消息推送到队列。交换机必须知道如何处理收到的消息。是该推送到一个特定的队列?还是推送到多个队列?还是丢弃?交换机类型定义了处理的规则。几种交换机类型:direct、topic、headers、fanout。现在先只看fanout。创建一个名为logs的该类型的交换机:

        channel.exchange_declare(exchange='logs',type='fanout')

fanout类型的交换机会广播所有收到的消息给所有它知道的队列。这正是我们的日志系统需要的。

        列出服务里的交换机可以使用rabbitmqctl:

        sudo rabbitmqctl list_exchanges

        匿名交换机,前面的章节我们使用了默认交换机,由空字符串标识:

        channel.basic_publish(exchange='',routing_key='hello', body=message)

参数exchange就是交换机的名字,空字符串表示默认或匿名交换机,消息被路由到由routing_key指定名字的队列,如果它存在的话。

        现在,我们可以将消息发布到命名的交换机了:

        channel.basic_publish(exchange='logs', routing_key='',body=message)

 

临时队列

        之前我们使用的队列都是有特定名字的。给队列命名很关键,我们需要把workers指定到相同的队列。当我们想在生产者和消费者间共享队列时,给队列命名很重要。

        但是我们的日志系统不是这种情况。我们想收到所有的消息,而不是一个子集。我们只关心当前的消息而不是旧的。我们需要这样做:

        首先,当我们连接到Rabbit我们需要一个新的空队列。我们可以使用随机的名字最好让服务为我们选一个名字来创建队列,只要我们不提供queue参数给queue_declare即可:

        result = channel.queue_declare()

result.method.queue就包含一个随机的队列名。

        其次,我们断开连接,队列应该被删除,exclusive参数可以做到:

        result =channel.queue_declare(exclusive=True)

 

绑定

        我们需要告诉交换机将消息发送到队列,交换机和队列之间的关系称为绑定。

        channel.queue_bind(exchange='logs',queue=result.method.queue)

        列出绑定,可以使用sudo rabbitmqctl list_bindings


提交log:

import pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.exchange_declare(exchange='logs', type='fanout')message = ' '.join(sys.argv[1:]) or "info: Hello World!"channel.basic_publish(exchange='logs', routing_key='', body=message)print(" [x] Sent %r" % message)connection.close()

        创建连接后,声明交换机,这步很必要,因为发布到一个不存在的交换机是被禁止的。

        如果还没有队列绑定到交换机,消息将被丢弃。

接收log:

import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.exchange_declare(exchange='logs', type='fanout')result = channel.queue_declare(exclusive=True)queue_name = result.method.queuechannel.queue_bind(exchange='logs', queue=queue_name)print(' [*] Waiting for logs. To exit press CTRL+C')def callback(ch, method, properties, body):    print(" [x] %r" % body)channel.basic_consume(callback, queue=queue_name, no_ack=True)channel.start_consuming()


0 0
原创粉丝点击