python:RabbitMQ 消息队列 学习笔记(1)
两个独立进程的交互:
(1)两个独立进程socket
(2)json存到文件或硬盘,很慢
(3)再开一个独立进程,作为服务器,处理socket里的各种粘包问题,维护网络通信:
a. RabbitMQ消息队列 基于erlang开发
b. ZeroMQ
c. ActiveMQ
.........
关于python的队列
- 内置的有两种,一种是线程queue,另一种是进程queue,但是这两种queue都是只能在同一个进程下的线程间或者父进程与子进程之间进行队列通讯,并不能进行程序与程序之间的信息交换,这时候我们就需要一个中间件,来实现程序之间的通讯。
- MQ并不是python内置的模块,而是一个需要你额外安装的程序,安装完毕后可通过python中内置的pika模块来调用MQ发送或接收队列请求。
pika使用:
(1)创建一个sokcet
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',))
(2)连接一个管道
channel = connection.channel()
(3)声明队列
channel.queue_declare(queue='msg_',durable=True)#
(4)生产者生产、消费者消费
生产者:
channel.basic_publish(exchange='',
routing_key='msg_',
body='Hello World!',
properties = pika.BasicProperties(
delivery_mode= 2,
)
)
消费者:
channel.basic_consume('msg_',
callback,
# auto_ack=False 消息被接收返回服务端,服务端删掉队列消息,否则会转给下一个
#没有回应,消息队列里的消息会一直存在,需要手动确认
auto_ack=False)
队列持久化:channel.queue_declare(queue='msg_',durable=True)#
消息持久化: properties = pika.BasicProperties(
delivery_mode= 2,
)
手动回应ch.basic_ack(delivery_tag=method.delivery_tag)
最多能处理队列中的1条消息channel.basic_qos(prefetch_count=1)
最简单的应用,代码区:
生产者:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#751
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
'localhost',))
channel = connection.channel()
# channel.queue_declare(queue='msg')
# 声明queue durable=True队列持久化,防止服务端异常关闭队列遗失
channel.queue_declare(queue='msg_',durable=True)
# n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
msg = ['呵呵',
'你傻啊',
'你不傻?',
'谁信'
]
for i in msg:
channel.basic_publish(exchange='',
routing_key='msg_',
body=i,
#消息持久化
properties = pika.BasicProperties(
delivery_mode= 2,
)
)
print(" [x] Sent '呵呵!'")
# channel.queue_delete('msg')
connection.close()
消费者:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#7512
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
'localhost',))
channel = connection.channel()
# You may ask why we declare the queue again ‒ we have already declared it in our previous core.
# We could avoid that if we were sure that the queue already exists. For example if send.py program
# was run before. But we're not yet sure which program to run first. In such cases it's a good
# practice to repeat declaring the queue in both programs.
# channel.queue_declare(queue='msg')
# 声明queue durable=True队列持久化,防止服务端异常关闭队列遗失
channel.queue_declare(queue='msg_',durable=True)
'''
ch:管道内存对象地址
method:一些信息
properties
body:内容
'''
def callback(ch, method, properties, body):
print("ch:",ch, "\nmethod:",method,"\nproperties" ,properties)
print(" [x] Received %r" % body.decode())
# ch.basic_ack(delivery_tag=method.delivery_tag)#手动回应
channel.basic_consume(queue='msg_',
on_message_callback=callback,
# auto_ack=False 消息被接收,要回应服务端,服务端删掉队列消息,否则会转给下一个
#没有回应,消息队列里的消息会一直存在,需要手动回应
auto_ack=False)
# 断线不处理,auto_ack=True 消息发了,队列的消息就没了
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
注:消息队列中,消费者多个的时候,生产者生产消息发送的时候,默认是轮询的方式发送。