RabbitMQ消息队列
RabbitMQ is the most widely deployed open source message broker.
RabbitMQ消息队列与threading Queue及Process Queue
1.threading Queue: 仅可实现在同一进程内的线程之间的交互;
2.进程Queue:父进程与子进程进行交互,或者同属于同一父进程下多个子进程间的交互;
3.那如何实现两个相互独立的Python进程通信呢?如果是java进程与Python进程的交互呢?->使用RabbitMQ
RabbitMQ的安装-win-详细戳这里
安装erlang->加ERLANG_HOME的用户变量->PATH中添加->%ERLANG_HOME%\bin->cmd下运行erl出现版本即成功
安装RabbitMQ->进Rabbitmq的cmd->rabbitmq-plugins.bat enable rabbitmq_management->启动rabbitmq-server.bat->登录http://localhost:15672/
RabbitMQ在Python上的clients-详细戳这里
实现最简单的队列通信
applications Produce Messages:
Exchanges Route and Filter Messages:On RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
Queues store and forward Messages:
Applications Consume Messages:
1.在一对多的消息分发时,采用轮询模式,即按照先后顺序,逐个处理produce发的消息;
2.永久保存队列使用channel.queue_declare(queue='hello', durable=True);
3.永久保存消息使用channel.basic_publish(properties=pika.BasicProperties(delivery_mode=2 ));
4.client对消息的确认channel.basic_consume(auto_ack=False),False是默认需要手动确认,True则为自动确认,如果消息得不到确认则会一直停留在MQ中;
5.ch.basic_ack(delivery_tag=method.delivery_tag) # 对消息的确认;
6.channel.basic_qos(prefetch_count=1) 公平分发->Client上配置,如果我有prefetch_count条消息未处理完,你就先不要给我发消息;
最简单的代码-Produce
import pika
connection = pika.BlockingConnection(
pika.ConnectionParameters('localhost') # 相当于建立一个最基本的socket,可以设置很多参数
)
channel = connection.channel() # 相当于声明一个管道
# 声明queue,一个名字叫"hello"的queue
# durable=True 让队列可以永久保存,即server端异常重启后仍然在
channel.queue_declare(queue='hello', durable=True)
channel.basic_publish(exchange='',
routing_key='hello', # queue的名字
body='Hello World!', # 消息内容
properties=pika.BasicProperties(delivery_mode=2 ) # 使消息持久化
)
print(" [x] Sent 'Hello World!'")
connection.close()
最简单的代码-Comsume
import pika
import time
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 code.
# 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='hello', durable=True)
def callback(ch, method, properties, body): # ch 声明的管道的内存对象地址 #
#print("-->", ch, method, properties)
print(" [x] Received %r" % body)
time.sleep(30)
print("30s is over!")
ch.basic_ack(delivery_tag=method.delivery_tag) # 对消息的确认
# 公平分发之如果我有条消息未处理完,你就先不要给我发消息
# 用于一对多时,各consume处理能力不同;
channel.basic_qos(prefetch_count=1)
# 消费消息
# 如果收到消息就调用callback函数,来处理消息
channel.basic_consume(queue="hello",
on_message_callback=callback,
auto_ack=False)
# auto_ack是用来决定消息是否自动确认,如果不自动确认则需要手动确认;
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming() # 开始收消息,一直收,不止这一条,会一直卡住
Message的广播
Exchanges Route and Filter Messages:An exchange is a very simple thing. On one side it receives messages from producers and the other side it pushes them to queues. The exchange must know exactly what to do with a message it receives. Should it be appended to a particular queue? Should it be appended to many queues? Or should it get discarded. The rules for that are defined by the exchange type.
Exchange在定义的时候是有类型的,以决定哪些Queue符合条件,可以接收消息:
1.fanout:所有bind到此exchange的queue都可以接收消息;->纯广播模式
2.direct:通过routingKey和exchange决定的哪个唯一的Queue可以接收消息;
3.topic:所有符合routingKey表达式的,routingKey所bind的queue可以接收消息;
4.headers:通过headers来决定把消息发给哪些queue;
Exchange的fanout类型举例
1.exchange的fanout的特点是,producer发消息不管有没有queue收,都不会在exchange中等待用户接收;
Producer端:
import pika
# 建立连接,及新建channel
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
# 基于channel创建一个fanout类型的exchange
channel.exchange_declare(exchange='logs', exchange_type='fanout')
message = "Info: Hello World!"
# 因为exchange的type是fanout即广播模式,则不需要特定绑定队列,即routing_key=''
channel.basic_publish(exchange='logs', routing_key='', body=message)
print(" [x] Sent %r" % message)
connection.close()
Consumer端:
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
# 基于channel创建一个fanout类型的exchange
channel.exchange_declare(exchange='logs', exchange_type='fanout')
# 因为是广播的fanout模式,所以若不用接收广播则可以将queue删除
# 以下就是创建了一个exclusive[排他的,独立的queue
# 这个queue会在client上的channel断开后,自动被rabbixmq清除
result = channel.queue_declare("", exclusive=True)
queue_name = result.method.queue # 获取自动生成的queue的名字
print(queue_name)
# exchange不与consume直接关联,而是与queue关联,queue又与comsume的channel关联;
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(queue=queue_name, on_message_callback=callback, auto_ack=True)
channel.start_consuming()
1111
end
官网文档-https://www.rabbitmq.com/getstarted.html
来源:https://www.cnblogs.com/FcBlogPythonLinux/p/12579394.html

