交换机-fanout

交换机 Exchange

通过消息队列,可以将消息分发给多个不同的消费者,但无法将一条消息同时分发给多个消费者。

通过交换机,可以非常简单地实现消息同时发给多个消费者的需求,如,发布订阅功能。

交换机有很多种模式,主要有:directtopicheadersfanout

交换机:一端连接生产者(接收消息),一端连着消费者的队列(将消息传出去)

补充

  • 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

补充:如果生产者发布消息时,还没有绑定的消费者,这个消息将直接丢掉。

posted @ 2020-05-10 18:08  the3times  阅读(535)  评论(0)    收藏  举报