zoukankan      html  css  js  c++  java
  • [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就可以

    日积月累,水滴石穿
  • 相关阅读:
    结巴分词 0.14 版发布,Python 中文分词库
    Lazarus 1.0.2 发布,Pascal 集成开发环境
    Android全屏 去除标题栏和状态栏
    服务器日志现 Android 4.2 传将添多项新特性
    Percona XtraBackup 2.0.3 发布
    长平狐 Android 强制设置横屏或竖屏 设置全屏
    NetBeans 7.3 Beta 发布,全新的 HTML5 支持
    CppDepend现在已经支持Linux
    GromJS 1.7.18 发布,服务器端的 JavaScript
    Apache OpenWebBeans 1.1.6 发布
  • 原文地址:https://www.cnblogs.com/lonelyisland/p/12757927.html
Copyright © 2011-2022 走看看