RabbitMq Publish/Subscribe消息发布订阅模式

官网就是最好的资料

之前的例子都基本都是1对1的消息发送和接收,即消息只能发送到指定的queue里,但有些时候你想让你的消息被所有的Queue收到,类似广播的效果,这时候就要用到exchange了,

An exchange is a very simple thing. On one side it receives messages from producers and the other side it pushes them to queues. The exchange must know exactly what to do with a message it receives. Should it be appended to a particular queue? Should it be appended to many queues? Or should it get discarded. The rules for that are defined by the exchange type.
Exchange在定义的时候是有类型的,以决定到底是哪些Queue符合条件,可以接收消息

  • fanout: 所有bind到此exchange的queue都可以接收消息
  • direct: 通过routingKey和exchange决定的那个唯一的queue可以接收消息
  • topic:所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息

表达式符号说明:#代表一个或多个字符,*代表任何字符
例:#.a会匹配a.a,aa.a,aaa.a等
*.a会匹配a.a,b.a,c.a等
注:使用RoutingKey为#,Exchange Type为topic的时候相当于使用fanout

下面着重看fanout模式。

官网上这么解释:
The fanout exchange is very simple. As you can probably guess from the name, it just broadcasts all the messages it receives to all the queues it knows. And that’s exactly what we need for our logger.
从字面角度讲,广播模式,仅仅跟exchange 关联的,跟queue是没有任何关系的。

下面直接上四段代码:
消息生产者 Client_fanout.py 消息发送,生产者
消息消费者 如下:
消息发布订阅Server_fanout.py
消息发布订阅Server_fanout2.py
消息发布订阅Server_fanout3.py
gitHub Demo源码地址

消息发布订阅Client_fanout.py
import pika
import time
credentials = pika.PlainCredentials('xiaoxia', 'xiaoxia')
connection = pika.BlockingConnection(pika.ConnectionParameters(
    '47.244.*.*', 5672, '/', credentials))
# 声明queue
channel = connection.channel()
channel.exchange_declare(exchange='round_robin_queue_mmm',
                         exchange_type='fanout')
# n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
n = 20
sum = 0
counter = 1
while counter <= n:
    channel.basic_publish(exchange='round_robin_queue_mmm',                 #Producer只能发送到exchange,它是不能直接发送到queue的,发送到默认exchange
                          routing_key='',         #路由key发送指定队列
                          body='Hello World:'+str(counter)) #发送的消息
    counter += 1
print(" [x] Sent 'Hello World!'")
connection.close()
消息发布订阅Server_fanout.py
import pika
import time
credentials = pika.PlainCredentials('xiaoxia', 'xiaoxia')
#建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters(
    '47.244.*.*', 5672, '/', credentials))
channel = connection.channel()
channel.exchange_declare(exchange='round_robin_queue_mmm', exchange_type='fanout')
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue

channel.queue_bind(exchange='round_robin_queue_mmm', queue=queue_name)
print(' [*] Waiting for logs. To exit press CTRL+C')
print(' [*] queue_name:'+queue_name)
消息发布订阅Server_fanout2.py
import pika
import time
credentials = pika.PlainCredentials('xiaoxia', 'xiaoxia')
#建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters(
    '47.244.*.*', 5672, '/', credentials))
channel = connection.channel()


channel.exchange_declare(exchange='round_robin_queue_mmm', exchange_type='fanout')
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
channel.queue_bind(exchange='round_robin_queue_mmm', queue=queue_name)
print(' [*] Waiting for logs. To exit press CTRL+C')
print(' [*] queue_name:'+queue_name)
def callback(ch, method, properties, body):  #定义回调函数用于取出队列中的数据
    print(" [x] Received %r" % body)
    time.sleep(1)
    ch.basic_ack(delivery_tag=method.delivery_tag)

channel.basic_consume(queue=queue_name,
                      on_message_callback=callback)          #不确认消息
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()                      #监听数据


消息发布订阅Server_fanout3.py
import pika
import time
credentials = pika.PlainCredentials('xiaoxia', 'xiaoxia')
#建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters(
    '47.244.*.*', 5672, '/', credentials))
channel = connection.channel()


channel.exchange_declare(exchange='round_robin_queue_mmm3', exchange_type='fanout')
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue

channel.queue_bind(exchange='round_robin_queue_mmm3', queue=queue_name)
print(' [*] Waiting for logs. To exit press CTRL+C')
print(' [*] queue_name:'+queue_name)


def callback(ch, method, properties, body):  #定义回调函数用于取出队列中的数据
    print(" [x] Received %r" % body)
    time.sleep(1)
    ch.basic_ack(delivery_tag=method.delivery_tag)

channel.basic_consume(queue=queue_name,
                      on_message_callback=callback)          #不确认消息
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()                      #监听数据

其中消费者1、2、3的queue都是不一样的,随机生成。如官网文档所说:
在这里插入图片描述

消费者1、2的Exchange是一样的,但是3的Exchage不一样。看下实际结果:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值