使用方法
#!/usr/bin/env python # -*- coding: utf-8 -*- """ RabbitMQ基础 http://www.cnblogs.com/wupeiqi/articles/5132791.html RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统。他遵循Mozilla Public License开源协议。 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据) 来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通 常是用于诸如远程过程调用的技术。排队指的是应用程序通过队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。 简单来说: RabbitMQ是在服务器上实现的一个消息队列,用于进行不同应用程序间的通信(应用程序不直接建立连接通信, 而是通过RabbiMQ实现的消息队列来进行数据交互) python操作RabbitMQ的模块:pika 安装:pip3 install pika 例:生产者消费者模型 对于RabbitMQ来说,生产和消费不再针对内存里的一个Queue对象,而是某台服务器上的RabbitMQ Server实现的消息队列。 """ import pika # 生产者 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.22')) # 创建连接RabbitMQ服务端的连接 channel = connection.channel() # 创建一个新频道 channel.queue_declare(queue='hello') # 频道中定义一个hello队列---如果该队列已存在,则忽略该句代码 # 开始向hello队列中发数据 channel.basic_publish(exchange='', routing_key='hello', body='hello,world!') print("[x] Send 'hello world!'") connection.close() # 关闭连接 ################################################################################################################# # 消费者 # connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.22')) # channel = connection.channel() # channel.queue_declare('hello') # # # # 回调函数 # # 参数:ch:频道(channel)、method:队列名字(hello)、# properties:连接RabbitMQ会有一些基本属性、body:从队列中取到的内容 # def callback(ch, method, properties, body): # print('[x] Received %r' % body) # # # 从hello队列中取数据,取完后会自动调用callback函数 # channel.basic_consume(callback, # queue='hello', # no_ack=True) # # print('[*] Waiting for messages,To exit press CTRL+C') # channel.start_consuming()
#!/usr/bin/env python # -*- coding: utf-8 -*- """ RabbitMQ使用---默认no_ack=False no_ack=False,如果消费者遇到情况(its channel is closed, connection is closed, or TCP connection is lost)挂掉了, 那么,RabbitMQ会重新将该任务添加到队列中。 简单来说: no_ack=False 表示消费者从队列中取数据,处理完毕后,需要告诉RabbitMQ服务端该条数据已处理,如果没有告诉,则服务端会认为消费 者出现问题,该条数据没有处理完成,会重新将该数据放回队列 no_ack=False 能保证数据不丢失,取出来的数据一定要处理完成才行,没处理完就会将数据放回,等待下次处理---------对性能有一定影响 no_ack=True 不能保证数据不丢失,不管取出来的数据是否处理完成,取出来就不管了---------性能比为False时高 """ import pika # 消费者 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.22')) channel = connection.channel() channel.queue_declear('hello') # 回调函数 # 参数:ch:频道(channel)、method:队列名字(hello)、# properties:连接RabbitMQ会有一些基本属性、body:从队列中取到的内容 # def callback(ch, method, properties, body): # print('[x] Received %r' % body) # # # 从hello队列中取数据,取完后会自动调用callback函数 # channel.basic_consume(callback, # queue='hello', # no_ack=True) # 回调函数 # 参数:ch:频道(channel)、method:队列名字(hello)、# properties:连接RabbitMQ会有一些基本属性、body:从队列中取到的内容 def callback(ch, method, properties, body): print(" [x] Received %r" % body) import time time.sleep(10) print('OK') ch.basic_ack(delivery_tag=method.delivery_tag) # 告诉RabbitMQ服务端数据已处理完成 # 从hello队列中取数据,取完后会自动调用callback函数 channel.basic_consume(callback, queue='hello', no_ack=False) # no_ack=False,消费者处理任务后,需要告诉服务端数据已处理完成 print('[*] Waiting for messages,To exit press CTRL+C') channel.start_consuming()
#!/usr/bin/env python # -*- coding: utf-8 -*- """ RabbitMQ使用 数据不丢失:在向RabbitMQ队列发数据的时候,告诉RabbitMQ服务端发送的数据要进行持久化保存,这样RabbitMQ服务端就会将收到的数据持久 化保存,即使RabbitMQ服务端出现故障,也不会影响该持久化的数据 """ import pika # 生产者 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.22')) # 创建连接RabbitMQ服务端的连接 channel = connection.channel() # 创建一个新频道 channel.queue_declare(queue='hello') # 频道中定义一个hello队列---如果该队列已存在,则忽略该句代码 # 开始向hello队列中发数据 channel.basic_publish(exchange='', routing_key='hello', body='hello,world!', properties=pika.BasicProperties(delivery_mode=2) # 告诉RabbitMQ服务端,数据要持久化保存 ) print("[x] Send 'hello world!'") connection.close() # 关闭连接
#!/usr/bin/env python # -*- coding: utf-8 -*- """ RabbitMQ使用 消息获取顺序: 默认消息队列里的数据是按照顺序被消费者拿走,例如:消费者1 去队列中获取 奇数 序列的任务,消费者2去队列中获取 偶数 序列的任务。 channel.basic_qos(prefetch_count=1) 表示谁来谁取,不再按照奇偶数排列 """ import pika # 消费者 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.22')) channel = connection.channel() channel.queue_declear('hello') # 回调函数 # 参数:ch:频道(channel)、method:队列名字(hello)、# properties:连接RabbitMQ会有一些基本属性、body:从队列中取到的内容 def callback(ch, method, properties, body): print(" [x] Received %r" % body) import time time.sleep(10) print('OK') ch.basic_ack(delivery_tag=method.delivery_tag) # 告诉RabbitMQ服务端数据已处理完成 channel.basic_qos(prefetch_count=1) # 表示取数据的时候,服务端按照队列顺序谁来谁取(默认每个消费者按照一定间隔来取数据) # 从hello队列中取数据,取完后会自动调用callback函数 channel.basic_consume(callback, queue='hello', no_ack=False) # no_ack=False,消费者处理任务后,需要告诉服务端数据已处理完成 print('[*] Waiting for messages,To exit press CTRL+C') channel.start_consuming()
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 发布订阅-----exchange type:fanout 发布订阅和简单的消息队列区别在于,发布订阅会将消息发送给所有的订阅者,而消息队列中的数据被消费一次便消失。所以,RabbitMQ实现发 布和订阅时,会为每一个订阅者创建一个队列,而发布者发布消息时,会将消息放置在所有相关队列中。 """ import pika import sys # 发布者 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.22')) # 创建连接 channel = connection.channel() # 创建频道 # 创建一个exchange,已存在则忽略该代码 channel.exchange_declare(exchange='logs_fanout', type='fanout') message = ' '.join(sys.argv[1:]) or "info: Hello World!" # 使用exchange发消息(exchange和队列的映射关系可以由订阅者做,订阅者将订阅的消息队列和exchange关联) channel.basic_publish(exchange='logs_fanout', routing_key='', body=message) print(" [x] Sent %r" % message) connection.close() ####################################################################################################################### # # 订阅者 # connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.22')) # 创建连接 # channel = connection.channel() # 创建频道 # # # 创建exchange,已存在则忽略该代码 # channel.exchange_declare(exchange='logs_fanout', # type='fanout') # # 随机创建队列,并随机取名 # result = channel.queue_declare(exclusive=True) # queue_name = result.method.queue # # # 创建exchange和消息队列的映射关系 # channel.queue_bind(exchange='logs_fanout', # 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()
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 关键字发送----exchang type:direct 之前示例,发送消息时明确指定某个队列并向其中发送消息,RabbitMQ还支持根据关键字发送,即:队列绑定关键字,发送者将数据根据关键字 发送到消息exchange,exchange根据 关键字 判定应该将数据发送至指定队列。 """ import pika import sys # 生产者 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.22')) # 创建连接 channel = connection.channel() # 创建频道 # 创建exchange channel.exchange_declare(exchange='logs_direct', type='direct') severity = sys.argv[1] if len(sys.argv) > 1 else 'info' # 定义关键字 message = ' '.join(sys.argv[2:]) or 'Hello World!' # 要发送的消息 #发送 channel.basic_publish(exchange='logs_direct', routing_key=severity, body=message) print(" [x] Sent %r:%r" % (severity, message)) connection.close() # 关闭 ####################################################################################################################### # 消费者 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.22')) # 创建连接 channel = connection.channel() # 创建频道 # 创建exchange channel.exchange_declare(exchange='logs_direct', type='direct') # 生成随机队列(也可以自定义队列) result = channel.queue_declare(exclusive=True) queue_name = result.method.queue # 生成关键字列表 severities = sys.argv[1:] if not severities: sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0]) sys.exit(1) # 遍历关键字列表,为当前监听的消息队列绑定关键字 for severity in severities: channel.queue_bind(exchange='logs_direct', queue=queue_name, routing_key=severity) # 绑定关键字 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()
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 模糊匹配----exchange type:topic 在topic类型下,可以让队列绑定几个模糊的关键字,之后发送者将数据发送到exchange,exchange将传入”路由值“和 ”关键字“进行匹配,匹配成功,则将数据发送到指定队列。 # 表示可以匹配 0 个 或 多个 单词 * 表示只能匹配 一个 单词 发送者路由值 队列中 old.boy old.* -- 匹配 old.boy.python old.* -- 不匹配(不能匹配'.'),只能匹配一个单词 old.boy.python old.# -- 匹配 """ import pika import sys # 生产者 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.22')) # 创建连接 channel = connection.channel() # 创建频道 # 创建exchange channel.exchange_declare(exchange='log_topic', 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='log_topic', routing_key=routing_key, body=message) print(" [x] Sent %r:%r" % (routing_key, message)) connection.close() ####################################################################################################################### # 消费者 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.22')) # 创建连接 channel = connection.channel() # 创建频道 # 创建exchange channel.exchange_declare(exchange='log_topic', type='topic') # 创建随机队列 result = channel.queue_declare(exclusive=True) queue_name = result.method.queue binding_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='log_topic', queue=queue_name, routing_key=binding_key) # 队列绑定模糊匹配的关键字,如:old.# print(' [*] Waiting for logs. To exit press CTRL+C') # 回调函数 def callback(ch, method, properties, body): print(" [x] %r:%r" % (method.routing_key, body)) ch.basic_ack(delivery_tag=method.delivery_tag) # 获取队列消息 channel.basic_consume(callback, queue=queue_name, no_ack=False) channel.start_consuming()
原理示意图
RabbitMQ发布订阅示意图
RabbitMQ关键字发送示意图
RabbitMQ模糊匹配示意图
关注我的公众号,不定期推送资讯
本文来自博客园,作者:链条君,转载请注明原文链接:https://www.cnblogs.com/MacoLee/articles/6125745.html