exchange工作模型有三种:fanout、direct、topic,具体如下:
一、发布订阅:fanout
(一) 基本原理:

类似于分发报刊,每一张报纸上的内容都是全套的,读者分别从报纸上读取内容,
发布订阅模式:将数据信息发布给所有订阅者,且数据队列中的信息被消费一次后就消失(no_ack=True)。
(二)具体流程:
RabbitMQ实现发布订阅时,为每一个订阅者创建一个队列,发布者发布消息时将消息放置在所有相关队列中:
1、生产者:声明一个交换机,并将数据信息载入,
2、消费者:指定交换机,并声明一个队列绑定到该交换机,
3、交换机:将生产者载入的数据信息,分发给绑定在其上的队列,每个队列收到的数据信息都是完整全套的,
4、消费者:从声明的队列中获取数据信息,并执行回调函数,
(三)代码实现:
#!/usr/bin/env python # -*- coding:utf-8 -*- # exchange工作模式:fanout import pika import sys # -----------------------生产者-------------------------------- connection = 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()
#!/usr/bin/env python # -*- coding:utf-8 -*- # exchange工作模式:fanout import pika #--------------------消费者---------------------- connection = 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.queue # 队列绑定交换机 channel.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()
二、关键字发送:direct

数据队列除了绑定交换机,还要绑定关键字(每一个队列可以绑定多个关键字;关键字不能为空,否则报错),
发送消息时,将数据信息和关键字同时载入交换机,交换机根据绑定在其上的数据队列的关键字,判断是否将数据发送给它,
#!/usr/bin/env python # -*- coding:utf-8 -*- # exchange工作模式:direct import pika import sys # -----------------------生产者-------------------------------- connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) channel = connection.channel() # 声明一个交换机 channel.exchange_declare(exchange='direct_logs',type='direct') # 将routing_key和body载入指定的交换机 severity = sys.argv[1] if len(sys.argv) > 1 else "info" message = ''.join(sys.argv[2:]) or "hello world!" channel.basic_publish(exchange='direct_logs', # 指定交换机 routing_key=severity, # 指定routing_key body=message) # 指定数据信息 print("[x] sent %r %r" % (severity,message)) connection.close()
#!/usr/bin/env python # -*- coding:utf-8 -*- # exchange工作模式:direct import pika import sys #--------------------消费者---------------------- connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) channel = connection.channel() # 指定交换机 channel.exchange_declare(exchange='direct_logs',type='direct') # 声明专用队列并获取队列名称 result = channel.queue_declare(exclusive=True) queue_name = result.method.queue # 输入routing_key,可多个,但不能为空, severities = sys.argv[1:] if not severities: sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0]) sys.exit(1) # 队列绑定交换机和多个routing_key for severity in severities: channel.queue_bind( exchange='direct_logs', queue=queue_name, routing_key=severity ) 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()
三、模糊匹配:topic

与上述direct模式相似,但绑定的关键字可以是模糊匹配:* 表示匹配一个单词,# 表示匹配0个或多个单词,如:
发送者路由值 队列中 old.boy.python old.* -- 不匹配 old.boy.python old.# -- 匹配
#!/usr/bin/env python # -*- coding:utf-8 -*- # exchange工作模式:topic import pika import sys # -----------------------生产者-------------------------------- connection = 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) > 1 else "anonymous.info" message = ''.join(sys.argv[2:]) or "hello world!" channel.basic_publish(exchange='topic_logs', # 指定交换机 routing_key=routing_key, # 指定routing_key body=message) # 指定数据信息 print("[x] sent %r %r" % (routing_key,message)) connection.close()
#!/usr/bin/env python # -*- coding:utf-8 -*- # exchange工作模式:topic import pika import sys #--------------------消费者---------------------- connection = 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.queue routing_keys = sys.argv[1:] if not routing_keys: sys.stderr.write("Usage: %s routing_keys......\n" % sys.argv[0]) sys.exit(1) for routing_key in routing_keys: channel.queue_bind( exchange='topic_logs', queue=queue_name, routing_key=routing_key, ) 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()
浙公网安备 33010602011771号