• [rabbitmq] python版本(五) 主题交换机


    更详细的可以看这里:https://rabbitmq.mr-ping.com/tutorials_with_python/[5]Topics.html
    这里只是简要笔记,以便快速回忆

    • 可以把topic看成是direct的一个升级版,可以匹配多个参数从而进行分类。
    • 比如上图,Q1可以匹配所有orange颜色的东西;Q2可以匹配兔子/懒惰的。不同的分类词之间用'.'分割
    • 对于上图".orange."和"..rabbit"只能匹配三个单词长度的routing key,"lazy.#"可以匹配任意长度的以lazy描述开头的routing key
      • 注意命令行要用""而不能用''对routing key进行设定
      • 如果传一个单词长度为4的routing key,比如"lazy.orange.male.rabbit"那么,不会匹配上面两种情况(长度不对),但是会匹配到"lazy.#"(只要lazy开头就可以,不论长度),消息最终传递到Q2

    emit_log_topic.py

    #!/usr/bin/env python
    import pika
    import sys
    
    #连接
    connection = pika.BlockingConnection(
        pika.ConnectionParameters(host='localhost'))
    channel = connection.channel()
    
    #声明交换机topic_logs 交换机类型topic
    channel.exchange_declare(exchange='topic_logs', exchange_type='topic')
    
    #routing_key设定为第一个命令行参数,如果没有则默认为'anonymous.info'
    routing_key = sys.argv[1] if len(sys.argv) > 2 else 'anonymous.info'
    #第二个命令行参数开始为发送的消息
    message = ' '.join(sys.argv[2:]) or 'Hello World!'
    #发布消息,交换机为topic_logs,routing key为上面设置的,body为消息体
    channel.basic_publish(
        exchange='topic_logs', routing_key=routing_key, body=message)
    print(" [x] Sent %r:%r" % (routing_key, message))
    connection.close()
    

    receive_logs_topic.py

    #!/usr/bin/env python
    import pika
    import sys
    
    #连接
    connection = pika.BlockingConnection(
        pika.ConnectionParameters(host='localhost'))
    channel = connection.channel()
    
    #声明交换机topic_logs,类型topic
    channel.exchange_declare(exchange='topic_logs', exchange_type='topic')
    
    #声明默认随机队列,名字存储在queue_name中;消费者退出后要进行处理
    result = channel.queue_declare(queue='', exclusive=True)
    queue_name = result.method.queue
    
    #第一个命令行参数开始为设定的binding_keys,一个或多个,少于一个报错
    binding_keys = sys.argv[1:]
    if not binding_keys:
        sys.stderr.write("Usage: %s [binding_key]...
    " % sys.argv[0])
        sys.exit(1)
    
    #绑定交换机和队列,设置routing_key
    for binding_key in binding_keys:
        channel.queue_bind(
            exchange='topic_logs', queue=queue_name, routing_key=binding_key)
    
    print(' [*] Waiting for logs. To exit press CTRL+C')
    
    
    def callback(ch, method, properties, body):
        print(" [x] %r:%r" % (method.routing_key, body))
    
    
    channel.basic_consume(
        queue=queue_name, on_message_callback=callback, auto_ack=True)
    
    channel.start_consuming()
    

    运行截图:

    图片说明:前三个terminal是从一开始就同步执行的,最后一个terminal是最后一步新建的
    需要注意的地方是:

    • '#' 匹配任意长度的单词,'*'匹配一个长度的单词
    • 命令行参数需要用""而不能用'',否则不会匹配到

    执行下边命令 接收所有日志:

    python receive_logs_topic.py "#"
    

    执行下边命令 接收来自”kern“设备的日志:

    python receive_logs_topic.py "kern.*"
    

    执行下边命令 只接收严重程度为”critical“的日志:

    python receive_logs_topic.py "*.critical"
    

    执行下边命令 建立多个绑定:

    python receive_logs_topic.py "kern.*" "*.critical"
    

    执行下边命令 发送路由键为 "kern.critical" 的日志:

    python emit_log_topic.py "kern.critical" "A critical kernel error"
    

    执行上边命令试试看效果吧。另外,上边代码不会对路由键和绑定键做任何假设,所以你可以在命令中使用超过两个路由键参数。

    一些问答:

    • 绑定键为 * 的队列会取到一个路由键为空的消息吗?
      不会 "*"只能匹配单词长度为1的路由键

    • 绑定键为 #.* 的队列会获取到一个名为..的路由键的消息吗?它会取到一个路由键为单个单词的消息吗?
      会获取到,"#.*"可以匹配长度大于1的路由键,名为..其实就是长度为3的路由键,可以匹配;单个单词即是长度为1也可以匹配

    • a.*.# 和 a.#的区别在哪儿?
      前者为a开头,但单词长度至少为2的一个路由键,后者长度至少为1就可以

    日积月累,水滴石穿
  • 相关阅读:
    浅入浅出EmguCv(一)OpenCv与EmguCv
    Selenium2入门(三)WebDriver API之Get
    Selenium2入门(二)WebDriver
    Selenium2入门(一)简介
    Tomcat部署Solr4.10.4
    On the Optimal Approach of Survivable Virtual Network Embedding in Virtualized SDN
    几篇虚拟映射文章粗读
    SDN网络虚拟化中有效协调的映射算法
    SDN网络中hypervisor带来的控制器时延(Hypervisor位置的优化)
    FlowerVisor理解
  • 原文地址:https://www.cnblogs.com/lonelyisland/p/12757927.html
Copyright © 2020-2023  润新知