上一篇说了路由键的功能,通过设置路由键,可以将消息发送到相应的队列,这里的路由键是要完全匹配,比如info消息的只能发到路由键为info的消息队列。
路由键模糊匹配,就是可以使用正则表达式,和常用的正则表示式不同,这里的话“#”表示所有、全部的意思;“*”只匹配到一个词。看完示例就能明白了。
这边继上一篇,还是用send.py和receive.py来实现路由键模糊匹配的功能。send.py表示发送端,receive.py表示接收端。实例的功能大概是这样:比如你有个知心好朋友,不管开心、伤心、工作上的还是生活上的事情都可以和她说;还有一些朋友可以分享开心的事情;还有一些朋友,你可以把不开心的事情和她说。
send.py代码分析
因为要进行路由键模糊匹配,所以交换机的类型要设置为topic,设置为topic,就可以使用#,*的匹配符号了。
5 | connection = pika.BlockingConnection(pika.ConnectionParameters( |
7 | channel = connection.channel() |
10 | channel.exchange_declare(exchange = 'messages' , type = 'topic' ) |
13 | routings = [ 'happy.work' , 'happy.life' , 'sad.work' , 'sad.life' ] |
16 | for routing in routings: |
17 | message = '%s message.' % routing |
18 | channel.basic_publish(exchange = 'messages' , |
上例中定义了四种类型的消息,容易理解,就不解释了,然后依次发送出去。
receive.py代码分析
同样,交换机的类型要设定为topic就可以了。从命令行接收参数的功能稍微调整了一下,就是没有参数时报错退出。
5 | connection = pika.BlockingConnection(pika.ConnectionParameters( |
7 | channel = connection.channel() |
10 | channel.exchange_declare(exchange = 'messages' , type = 'topic' ) |
13 | routings = sys.argv[ 1 :] |
15 | print >> sys.stderr, "Usage: %s [routing_key]..." % (sys.argv[ 0 ],) |
19 | result = channel.queue_declare(exclusive = True ) |
20 | queue_name = result.method.queue |
21 | for routing in routings: |
22 | channel.queue_bind(exchange = 'messages' , |
26 | def callback(ch, method, properties, body): |
27 | print " [x] Received %r" % (body,) |
29 | channel.basic_consume(callback, queue = queue_name, no_ack = True ) |
31 | print ' [*] Waiting for messages. To exit press CTRL+C' |
32 | channel.start_consuming() |
打开四个终端,一个运行如下,表示任何事情都可以和她说:
python receive.py "#"
另外一个终端 运行如下,表示可以和她分享开心的事:
python receive.py "happy.*"
第三个运行如下,表示工作上的事情可以和她分享:
python receive.py "*.work"
最后一个运行python send.py。结果不难想象出来,就不贴出来了。
参考文章:http://www.rabbitmq.com/tutorials/tutorial-five-python.html
在参考文章的最后面有提到几个难点,笔者自己做了测试,供大家参考:
1、发送信息时,如果不设置路由键,那么路由键设置为”*”的接收端是否能接收到消息?
发送信息时,如果不设置路由键,默认是表示广播出去,理论上所有接收端都可以收到消息,但是笔者试了下,路由键设置为"*"的接收端收不到任何消息。
只有发送消息时,设置路由键为一个词,路由键设置为"*"的接收端才能收到消息。在这里,每个词使用"."符号分开的。
2、发送消息时,如果路由键设置为”..”,那么路由键设置为”#.*”的接收端是否能接收到消息?如果发送消息时,路由键设置为一个词呢?
两种情况,笔者都测试过了,可以的。
3、”a.*.#” 和”a.#”的区别
"a.#"只要字符串开头的一个词是a就可以了,比如a、a.haha、a.haha.haha。而这样的词是不行的,如abs、abc、abc.haha。
"a.*.#"必须要满足a.*的字符串才可以,比如a.、a.haha、a.haha.haha。而这样的词是不行的,如a。
弄完上面的这些个问题,笔者觉着有些钻牛角尖了,不过既然官方有提出来,就钻一回吧。