RabbitMQ中的Exchange Types
来源:互联网 发布:淘宝能买到呼死你吗 编辑:程序博客网 时间:2024/06/11 04:43
整理自:
- https://www.rabbitmq.com
- https://www.cloudamqp.com/blog/2015-09-03-part4-rabbitmq-for-beginners-exchanges-routing-keys-bindings.html
- 《RabbitMQ实战》
在RabbitMQ中, 生产者把消息发送到一个交换机(exchange)上,而不是直接发布到队列上。交换机是一个消息路由代理,它负责把消息路由到不同的队列中去(通过header 属性,bindings,routing key)。
绑定(binding)是队列和交换机的一个链接。
路由键(routing key)是一个消息属性,交换机在决定把这条消息路由到队列中时,也许会根据这个key来做判断。(这取决于交换机的类型)
标准的RabbitMQ消息流:
- 生产者把消息发布到交换机上
- 交换机收到消息,负责把消息路由
- 一个队列和交换机的绑定被建立,交换机把消息路由到队列中
- 队列中的消息被消费者处理
交换机、连接(connections)和队列在创建时可以被一些参数来配置,比如durable, temporary, 和 auto delete。Durable的交换机在服务器重启时会存活下来,直到被明确的删除。Temporary的交换器在RabbitMQ关闭的时候就没了。Auto Deleted的交换机在最后一个被绑定的对象解绑时就被删去了。
在RabbitMQ中,有四种不同的交换机。
一、Direct Exchange
Direct交换机根据消息的路由键把消息传递给队列。路由键是生产者加到消息头部的一个消息属性。路由键可以被视作交换机用来决定怎么路由这个消息的一个地址。消息会进入到binding key完全符合消息的路由键的队列中。
在你想要用一个简单的字符串标识符来区分被发布到同一个交换机上的消息时, direct交换机就有用了。想象队列A(下图中的create_pdf_queue)被binding key pdf_create绑定在direct交换机 (pdf_events) ,当一个路由键为pdf_create的消息到达这个direct交换机时,交换机把它路由到binding_key = routing_key的队列中去,在这里,也就是队列A。
(也可以多个队列用同一个routing key来绑定,这样的话消息会被发送到所有的这些队列中)
例子:
路由键为pdf_log的消息被发送到了交换机pdf_events,消息被路由到pdf_log_queue因为路由键pdf_log符合binding key pdf_log。
如果消息的路由键不符合任何的binding key,那么这个消息将被丢弃。
默认交换机
默认交换机是一个预先定义的direct交换机,没有名字,经常被空字符串“”来引用。 当你使用默认交换机时,你的消息会被路由到名字和消息的路由键相等的队列中。每个队列都自动绑定到默认交换机,binding key就是队列的名字。
默认交换机的代码示例:
producer.py:
#!/usr/bin/env pythonimport pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.queue_declare(queue='task_queue', durable=True)message = ' '.join(sys.argv[1:]) or "Hello World!"channel.basic_publish(exchange='', routing_key='task_queue', body=message, properties=pika.BasicProperties( delivery_mode = 2, # make message persistent ))print(" [x] Sent %r" % message)connection.close()
worker.py:
#!/usr/bin/env pythonimport pikaimport timeconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.queue_declare(queue='task_queue', durable=True)print(' [*] Waiting for messages. To exit press CTRL+C')def callback(ch, method, properties, body): print(" [x] Received %r" % body) time.sleep(body.count(b'.')) print(" [x] Done") ch.basic_ack(delivery_tag = method.delivery_tag)channel.basic_qos(prefetch_count=1)channel.basic_consume(callback, queue='task_queue')channel.start_consuming()
二、Topic Exchange
#!/usr/bin/env pythonimport pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.exchange_declare(exchange='topic_logs', type='topic')routing_key = sys.argv[1] if len(sys.argv) > 2 else 'anonymous.info'message = ' '.join(sys.argv[2:]) or 'Hello World!'channel.basic_publish(exchange='topic_logs', routing_key=routing_key, body=message)print(" [x] Sent %r:%r" % (routing_key, message))connection.close()
consumer.py:
#!/usr/bin/env pythonimport pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.exchange_declare(exchange='topic_logs', type='topic')result = channel.queue_declare(exclusive=True)queue_name = result.method.queuebinding_keys = sys.argv[1:]if not binding_keys: sys.stderr.write("Usage: %s [binding_key]...\n" % sys.argv[0]) sys.exit(1)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(callback, queue=queue_name, no_ack=True)channel.start_consuming()
三、Fanout Exchange
示例代码:
emit_log.py:
#!/usr/bin/env pythonimport pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.exchange_declare(exchange='logs', type='fanout')message = ' '.join(sys.argv[1:]) or "info: Hello World!"channel.basic_publish(exchange='logs', routing_key='', body=message)print(" [x] Sent %r" % message)connection.close()
receive_logs.py:
#!/usr/bin/env pythonimport pikaconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.exchange_declare(exchange='logs', type='fanout')result = channel.queue_declare(exclusive=True)queue_name = result.method.queuechannel.queue_bind(exchange='logs', queue=queue_name)print(' [*] Waiting for logs. To exit press CTRL+C')def callback(ch, method, properties, body): print(" [x] %r" % body)channel.basic_consume(callback, queue=queue_name, no_ack=True)channel.start_consuming()
四、Headers Exchange
Headers交换机基于包括headers和可选值的参数来做路由。Headers交换机和Topic交换机非常像,但是它是基于header的值而不是路由键来做路由的。一条消息被认为是匹配的,如果它header的值与绑定中指定的值相同的话。
一个叫做”x-match“的特殊的参数说明是否所有的header都必须匹配或者只需要有一个, 它有两种值, 默认为"all",表示所有的header键值对都必须匹配;而"any"表示至少一个header键值对需要匹配。Headers可以被int或者string组成。
- 交换机与队列A的绑定的参数: format = pdf, type = report
- 交换机与队列B的绑定的参数: format = pdf, type = log
- 交换机与队列C的绑定的参数: format = zip, type = report
如果没有任何匹配的队列,消息会被丢弃。RabbitMQ提供了一个AMQP的拓展,"Dead Letter Exchange", 可以捕获到那些没有被成功传达的消息。
示例:
emitter.py:
#!/usr/bin/env pythonimport pikaconnection = pika.BlockingConnection(pika.ConnectionParameters( host='localhost'))channel = connection.channel()channel.exchange_declare(exchange='testing', type='headers')try: while True: fields = {} data = input('>') if '=' in data: key, val = data.split('=') fields[key] = val continue channel.basic_publish(exchange = 'testing', routing_key = '', body = data, properties = \ pika.BasicProperties(headers = fields)) print (' [x] Send {0} with headers: {1}'.format(data, fields))except KeyboardInterrupt: print ('Bye')finally: connection.close()
receiver.py:
#!/usr/bin/env pythonimport pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters( host='localhost'))channel = connection.channel()channel.exchange_declare(exchange='testing', type='headers')result = channel.queue_declare(exclusive=True)if not result: print ('Queue didnt declare properly!') sys.exit(1)queue_name = result.method.queuechannel.queue_bind(exchange='testing', queue = queue_name, routing_key = '', arguments = {'ham': 'good', 'x-match':'any'})def callback(ch, method, properties, body): print ("{headers}:{body}".format(headers = properties.headers, body = body))channel.basic_consume(callback, queue = queue_name, no_ack=True)try: channel.start_consuming()except KeyboardInterrupt: print ('Bye')finally: connection.close()
- RabbitMQ中的Exchange Types
- RabbitMQ各种交换机类型Exchange Types介绍
- RabbitMQ各种交换机类型Exchange Types介绍
- RabbitMQ各种交换机类型Exchange Types介绍
- RabbitMQ各种交换机类型Exchange Types介绍
- RabbitMQ各种交换机类型Exchange Types介绍
- RabbitMQ各种交换机类型Exchange Types介绍
- RabbitMQ各种交换机类型Exchange Types介绍
- 关于RabbitMQ中的Exchange Type的说明
- RabbitMQ exchange
- [Erlang 0089] RabbitMQ Exchange
- RabbitMQ 三种Exchange
- RabbitMQ之Exchange
- RabbitMQ 三种Exchange
- RabbitMQ 三种Exchange
- rabbitmq(五)topic exchange
- RabbitMQ 三种Exchange
- RabbitMQ Exchange 类型介绍
- 【CSS】4.选择器
- mybatis-generator
- 【原创】基于FPGA的数码管按键显示(two_key)
- Centos6.8中kdump的设置问题
- 在O(1)时间复杂度删除链表节点
- RabbitMQ中的Exchange Types
- 126篇殿堂级深度学习论文分类整理 从入门到应用(上)
- 3.Scala中的函数
- Java多线程探究-读写锁ReentrantReadWriteLock
- Python基础语法
- 点击按钮实现缩放动画
- Redis通用命令
- 宽度优先搜索
- 126篇殿堂级深度学习论文分类整理 从入门到应用(下)