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