RabbitMQ学习小结(五)----主题交换机

前面的一小节路由键是精确匹配的,

路由键的功能,通过设置路由键,可以将消息发送到相应的队列,这里的路由键是要完全匹配,比如info消息的只能发到路由键为

info的消息队列。有时用需要路由键模糊匹配,本篇主要演示了路由键模糊匹配的工作方式,主要依赖于使用另一种更复杂的交换

机—— 主题交换机。

一、主题交换机

1、发送到主题交换机(topic exchange)的消息不可以携带随意什么样子的路由键(routing_key),它的路由键必须是一个由.分

开的词语列表。这些单词随便是什么都可以,但是最好是跟携带它们的消息有关系的词汇。

子:"stock.usd.nyse", "nyse.vmw", "quick.orange.rabbit"。词语的个数可以随意,但是不要超过255字节。

2、绑定键也必须拥有同样的格式。主题交换机背后的逻辑跟直连交换机很相似 —— 一个携带着特定路由键的消息会被主题交换

递给绑定键与之想匹配的队列。但是它的绑定键和路由键有两个特殊应用方式:

"*" (星号) 用来表示一个单词。(必须出现的)

"#" (井号) 用来表示任意数量(零个或多个)单词。

3、大家可以根据下图,猜测哪些路由键会被发送到相应的队列,就是类似于正则的匹配,但是比正则简单太多了,有兴趣的可以到

网查看完整内容,我就不再阐述了。

  RabbitMQ学习小结(五)----主题交换机_第1张图片

4、主题交换机

当一个队列的绑定键为 "#"(井号) 的时候,这个队列将会无视消息的路由键,接收所有的消息。

当 * (星号) 和 # (井号) 这两个特殊字符都未在绑定键中出现的时候,此时主题交换机就拥有的直连交换机的行为。

所以主题交换机也就实现了扇形交换机的功能,和直连交换机的功能。

二、实例演示

send.py表示发送端,receive.py表示接收端。实例的功能大概是这样:比如你有个知心好朋友,不管开心、伤心、工作上的还是生

活上的事情都可以和她说;还有一些朋友可以分享开心的事情;还有一些朋友,你可以把不开心的事情和她说。

1、生产者
(1) 创建连接和通道

(2) 创建交换机(主题交换机)

(3) 发送消息到指定交换机,并将消息中指定routing_key(注意key的规则)

2、消费者

(1) 创建连接和通道

(2) 创建交换机(主题交换机)

(3) 创建匿名队列(每个消费者都要创建的独立的队列,用于接收路由后消息)

(4) 创建绑定(通过路由键绑定交换机队列关系,确定队列处理交换机中的哪些消息,注意路由键的正则规则)

(5) 在指定交换机处理消息

3、程序

(1)、send.py

 因为要进行路由键模糊匹配,所以交换机的类型要设置为topic,设置为topic,就可以使用#,*的匹配符号了。

#!/usr/bin/python

import pika
 
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
 
#定义交换机,设置类型为topic
channel.exchange_declare(exchange='messages', type='topic')
 
#定义路由键
routings = ['happy.work', 'happy.life', 'sad.work', 'sad.life']
 
#将消息依次发送到交换机,并设定路由键
for routing in routings:
    message = '%s message.' % routing
    channel.basic_publish(exchange='messages',routing_key=routing,body=message) #将携带路由键的消息依次发给交换机
    print message
 
connection.close()
(2)、receive.py

 交换机的类型要设定为topic就可以了。从命令行接收参数的功能稍微调整了一下,就是没有参数时报错退出。

#!/usr/bin/python
import pika, sys
 
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
 
#定义交换机,设置类型为topic
channel.exchange_declare(exchange='messages', type='topic')
 
#从命令行获取路由参数,如果没有,则报错退出
routings = sys.argv[1:]
if not routings:  #取反
    print "Usage: %s [routing_key]..." % (sys.argv[0],)
    exit()
 
#生成临时队列,并绑定到交换机上,设置路由键
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue
for routing in routings:
    channel.queue_bind(exchange='messages',queue=queue_name,routing_key=routing)
 
def callback(ch, method, properties, body):
    print " [x] Received %s" % (body,)
 
channel.basic_consume(callback, queue=queue_name, no_ack=True)
 
print ' [*] Waiting for messages. To exit press CTRL+C'
channel.start_consuming()
打开四个终端,一个运行如下,表示任何事情都可以和她说:python receive.py "#"

另外一个终端 运行如下,表示可以和她分享开心的事:python receive.py "happy.*"

第三个运行如下,表示工作上的事情可以和她分享:python receive.py "*.work"

最后一个运行python send.py。可得到程序的运行结果。

三、官网提出的几个问题

1、发送消息时,如果路由键设置为”..”,那么路由键设置为”#.*”的接收端是否能接收到消息?如果发送消息时,路由键设置

为一个词呢?

两种情况,笔者都测试过了,可以的。

2、”a.*.#” 和”a.#”的区别

"a.#"只要字符串开头的一个词是a就可以了,比如a、a.haha、a.haha.haha。而这样的词是不行的,如abs、abc、abc.haha。

"a.*.#"必须要满足a.*的字符串才可以,比如a.、a.haha、a.haha.haha。而这样的词是不行的,如a。

我觉得根据官网和别人的博客总结,最终还是很清楚的把主题交换机搞清楚了。所以说,灵活运用,根据应用场景合理选择不同的

交换机!主题交换机进行路由的模糊匹配就到这里。


你可能感兴趣的:(openstack组件研究)