交换机-fanout
交换机 Exchange
通过消息队列,可以将消息分发给多个不同的消费者,但无法将一条消息同时分发给多个消费者。
通过交换机,可以非常简单地实现消息同时发给多个消费者的需求,如,发布订阅功能。
交换机有很多种模式,主要有:direct
、topic
、headers
、fanout
。
交换机:一端连接生产者(接收消息),一端连着消费者的队列(将消息传出去)
补充:
-
RabbitMQ中,生产者发出的消息不是直接交给队列的,而是需要经过交换机,再交给不同的队列。
-
默认交换机。之前使用的消息队列,其实也使用了交换机。只不过使用的是默认交换机
exchange=''
channel.basic_publish(exchange='', routing_key='hello', body=message) # exchange参数是指定交换机的名字,当交换机名字为空时,默认将消息交给参数routing_key指定的队列 # 所以,当我们使用有名字的交换机时,就无需再指定参数routing_key所指代的队列,但仍要赋空值routing_key=''
-
查看服务器上的交换机
sudo rabbitmqctl list_exchanges # linux # 此时会多出一些以`amq.`开头命名的交换机,无需关心和使用他们,这是系统默认的。
fanout模式
fanout
模式下,生产者发出去的消息,会交给绑定到交换机上的所有队列,即所有的消费者都可以得到一份完全相同的消息。
fanout
是完完全全的发布订阅模式(publish/subscribe),只要生产者发布消息,所有的消费者都将得到一份完全相同的消息。
channel.exchange_declare(exchange='logs',
exchange_type='fanout')
生产者的设置:通过以下三步,可以将消息发给指定的交换机。
- 第一步,连接RabbitMQ
- 第二步,建交换机,参数
exchange
表示交换机的名字,参数exchange_type
指的是交换机的类型。 - 第三步,发布消息,参数
exchange
表示使用的交换机,此时routing_key
赋值为空即可。
注意:建立间接后必须先声明交换机,才能往这个交换机上发布消息。
生产者.py
import pika
# 第一步,连接rabbitmq
parameters = pika.ConnectionParameters(host='localhost')
connection = pika.BlockingConnection(parameters)
channel = connection.channel()
# 第二步,建交换机
channel.exchange_declare(exchange='log', exchange_type='fanout')
# 第三步,发消息
channel.basic_publish(exchange='log', routing_key='', body='Hello World!')
print(" [x] Sent 'Hello World!'")
# 主动关闭连接
connection.close()
消费者的设置:消费者的设置相对复杂,需要建交换机,同时还要有自己的队列,并将队列绑定到交换机。
-
第一步,连接RabbitMQ
-
第二步,建交换机,参数设置同生产者一致
-
第三步,建临时队列(Temporary queues)并绑定交换机,队列自动命名
queue=''
,自动回收队列exclusive=True
;绑定交换机时提供交换机名字和,队列名字。队列名字获取result.method.queue
-
第四步,设置监听参数
-
第五步,开启监听
消费者.py
import pika
# 第一步,连接rabbitmq
parameters = pika.ConnectionParameters(host='localhost')
connection = pika.BlockingConnection(parameters)
channel = connection.channel()
# 第二步,建交换机
channel.exchange_declare(exchange='log', exchange_type='fanout')
# 第三步,建队列队并绑定到交换机
result = channel.queue_declare(queue='', exclusive=True) # 队列设为空,会自动命名队列
queue_name = result.method.queue # 获取队列名 result.method.queue
channel.queue_bind(exchange='log', queue=queue_name)# 绑定到指定交换机
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
# 第四步,设置监听参数
channel.basic_consume(
queue=queue_name, on_message_callback=callback, auto_ack=True) # 手动确认自动确认都可以
# 第五步,开始监听
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
补充
临时队列
临时队列有两个特点,名字自动生成,随机且唯一;队列不用时,自动回收。
使用临时队列的目的:每次使用的都是一个干净队列;当消费者失去连接时,RabbitMQ会自动回收队列。
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
# 获取随机的队列名,如amq.gen-JzTY20BRgKO-HjmUJj0wLg
# 参数 exclusive设置为True,表示当队列不用时自动回收
绑定
绑定就是建立交换机和队列之间的关系。绑定操作时非常重要的,它的作用是告诉交换机,将消息发送给那些队列,队列拿到消息后,才能交给消费者。
channel.queue_bind(exchange='logs',
queue=result.method.queue)
查看当前服务器上存在的绑定关系
sudo rabbitmqctl list_bindings #linux
补充:如果生产者发布消息时,还没有绑定的消费者,这个消息将直接丢掉。