RabbitMQ基本用法、消息分发模式、消息持久化、广播模式
RabbitMQ基本用法
- 进程queue用于同一父进程创建的子进程间的通信
- 而RabbitMQ可以在不同父进程间通信(例如在word和QQ间通信)
示例代码
- 生产端(发送)
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
#相当于建立一个socket,连接本地的RabbitMQ,默认端口:5672
channel = connection.channel()#声明一个通信管道(信道)
#在管道里什么一个queue
channel.queue_declare(queue='hello')#声明一个名称为hello的queue
#通过管道发送消息
channel.basic_publish(exchange='',
routing_key='hello',#queue的名字
body='Hellow Word!')#消息主体
connection.close()#关闭连接
- 消费端(接收)
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
#不确定生产端或消费端谁先运行,因此为了避免错误,消费端也要申请一个queue
#消费端先运行,如果没申请这个queue,生产端还没建立这个queue,因此报错
channel.queue_declare(queue='hello')
def callback(ch,method,properties,body):
#ch,管道(信道)channel的内存地址
#method,设置的一些基本信息
#properties,
#body,消息主体,二进制数据
print(ch,method,properties)
print('[x] Received %r'%body)
#声明要收消息
channel.basic_consume(
callback,#如果收到消息就调用回调函数处理消息
queue='hello',#queue的名字
no_ack=True#不确认,是否处理完callback,给rabbitmq返回确认信息
)
#开始收消息
channel.start_consuming()#开启后一直收消息,没消息则卡住
消息分发
RabbitMQ消息分发(一对多)
- 一个生产者,多个消费者
- 多个消费者时,是轮询机制,依次分发给消费者。(每个消费者按顺序依次消费)
no_act
设置是否确认消息处理完
- 设置no_act = True,消费者不发送确认信息,RabbitMQ从发送消息队列后,不管消费者是否处理完,删除queue
- 设置no_act = False,RabbitMQ等待消费者的callback处理完,发送确认信息,如果此时消费者down了,则Rabbit把消息轮询发送给下一个消费者,等待确认才会删除queue
- 去掉no_act = True(默认为False),需要在回调函数中新增代码,手动向RabbitMQ发送确认信息
ch.basic_ack(delivery_tag=method.delivery_tag)
消息持久化
rabbitmq目录下启动cmd,命令:rabbitmqctl.bat list_queues
查看当前queue列表
当我们需要消息不会丢失(RabbitMQ server宕机时),需要进行消息持久化
- 1、在申明队列是加上参数使其持久化,生产者和消费者都需要申明
channel.queue_declare(queue='hello',durable=True)
队列持久化- 2、在生产端发送消息函数时加入参数使消息持久化
- 消息持久化
channel.basic_publish(
exchange='',
routing_key='hello',#queue的名字
body='Hellow Word!'
porperties=pika.BasicProperties(
delivery_mode=2#使队列里的消息持久化
)
)#消息主体
广播模式
消息公平分发
- 如果Rabbit只管按顺序把消息发到各个消费者身上,不考虑消费者负载的话,很可能出现,一个机器配置不高的消费者那里堆积了很多消息处理不完,同时配置高的消费者却一直很轻松。为解决此问题,可以在各个消费者端,配置perfetch=1,意思就是告诉RabbitMQ在我这个消费者当前消息还没处理完的时候就不要再给我发新消息了。
- 在消费端channel.basic_consume()函数前新增一条代码
channel.basic_qos(prefetch_count=1)
- 解释:如果有2个消费者(a,b),a处理消息比较慢,b比较快;RabbitMQ是轮询发送消息,依次给a一条,给b一条,再给a.....。当在消费者端设置以上代码时,a还在处理,那么RabbitMQ不会给a发送,只会给b
广播模式(消息是实时的,发送时没有启动接收端,消息丢失)
- 1、发送端将消息发送到RabbitMQ的消息转发器(exchange)
- 2、转发器(Exchange)遍历所有绑定它的queue,将消息广播给queue
- 3、接收端从queue里获取接收消息
- 4、使用此queue的消费者断开后,此queue删除
- 设置exchange转发器
- Exchange在定义的时候是有类型的,以决定到底是哪些Queue符合条件,可以接收消息
- fanout: 所有bind到此exchange的queue都可以接收消息
- direct: 通过routingKey和exchange决定的那个唯一的queue可以接收消息
- topic:所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息
给所有bind此exchange的发送消息
- 发送端
import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='logs',
type='fanout')#广播模式,不用申明queue指定queue名
#设置exchange为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()
- 接收端
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名字,rabbit会随机分配一个名字,exclusive=True会在使用此queue的消费者断开后,自动将queue删除
queue_name = result.method.queue#拿到这个随机分配的queue名
channel.queue_bind(exchange='logs',#绑定发送端的exchange
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()
有选择的广播(接受者过滤接收消息exchange type=direct)
- 生产者
import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='direct_logs',
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='direct_logs',
routing_key=severity,
body=message)
print(" [x] Sent %r:%r" % (severity, message))
connection.close()
- 消费者
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
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='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:%r" % (method.routing_key, body))
channel.basic_consume(callback,
queue=queue_name,
no_ack=True)
channel.start_consuming()
细致的消息过滤()
- 生产者
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,
body=message)
print(" [x] Sent %r:%r" % (routing_key, message))
connection.close()
- 消费者
- 参数为
#
,不过滤收所有 mysql.*
,收所有mysql开头的消息
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
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='topic_logs',
queue=queue_name,
routing_key=binding_key)
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()
RabbitMQ基本用法、消息分发模式、消息持久化、广播模式的更多相关文章
- RocketMQ 原理:消息存储、高可用、消息重试、消息幂等性
目录 消息存储 消息存储方式 非持久化 持久化 消息存储介质 消息存储与读写方式 消息存储结构 刷盘机制 同步刷盘 异步刷盘 小结 高可用 高可用实现 主从复制 负载均衡 消息重试 顺序消息重试 无序 ...
- 工作队列work queues 公平分发(fair dispatch) And 消息应答与消息持久化
生产者 package cn.wh.work; import cn.wh.util.RabbitMqConnectionUtil; import com.rabbitmq.client.Channel ...
- (六)RabbitMQ消息队列-消息任务分发与消息ACK确认机制(PHP版)
原文:(六)RabbitMQ消息队列-消息任务分发与消息ACK确认机制(PHP版) 在前面一章介绍了在PHP中如何使用RabbitMQ,至此入门的的部分就完成了,我们内心中一定还有很多疑问:如果多个消 ...
- rabbitmq消息队列,消息发送失败,消息持久化,消费者处理失败相关
转:https://blog.csdn.net/u014373554/article/details/92686063 项目是使用springboot项目开发的,前是代码实现,后面有分析发送消息失败. ...
- RabbitMQ消息队列(六)-消息任务分发与消息ACK确认机制(.Net Core版)
在前面一章介绍了在.Net Core中如何使用RabbitMQ,至此入门的的部分就完成了,我们内心中一定还有很多疑问:如果多个消费者消费同一个队列怎么办?如果这几个消费者分任务的权重不同怎么办?怎么把 ...
- 轻松搞定RabbitMQ(三)——消息应答与消息持久化
转自 http://blog.csdn.net/xiaoxian8023/article/details/48710653 这个官网的第二个例子中的消息应答和消息持久化部分.我把它摘出来作为单独的一块 ...
- Spring Boot 之 RabbitMQ 消息队列中间件的三种模式
开门见山(文末附有消息队列的几个基本概念) 1.直接模式( Direct)模式 直白的说就是一对一,生产者对应唯一的消费者(当然同一个消费者可以开启多个服务). 虽然使用了自带的交换器(Exchang ...
- Kafka分片存储、消息分发和持久化机制
Kafka 分片存储机制 Broker:消息中间件处理结点,一个 Kafka 节点就是一个 broker,多个 broker 可以组成一个 Kafka集群. Topic:一类消息,例如 page vi ...
- RabbitMQ原理与相关操作(三)消息持久化
现在聊一下RabbitMQ消息持久化: 问题及方案描述 1.当有多个消费者同时收取消息,且每个消费者在接收消息的同时,还要处理其它的事情,且会消耗很长的时间.在此过程中可能会出现一些意外,比如消息接收 ...
随机推荐
- x0vncserver
x0vncserver -display :0 -passwordfile ~/.vnc/passwd
- APP设计规范
设计师DPI指南 本指南旨在为初级到中级设计人员提供“入门”或介绍性阅读,他们希望从一开始就学习或获得有关跨DPI和跨平台设计的更多知识. 尽可能少的数学和没有不可解析的图形,只需在简短的部分中订购直 ...
- pytorch contiguous的使用
contiguous一般与transpose,permute,view搭配使用 即使用transpose或permute进行维度变换后,调用contiguous,然后方可使用view对维度进行变形. ...
- C++_静态类成员
在C++中,静态成员是属于整个类的而不是某个对象. 静态成员变量只存储一份供所有对象共用,所以在所有对象中都可以共享它. 使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可 ...
- 无限期使用WebStorm方式
http://blog.csdn.net/DorAction/article/details/79332421 1.下载补丁:JetbrainsCrack-2.7-release-str.jar ht ...
- C#学习之按钮点击事件
描述:asp.net中服务器控件Button的点击事件OnClientClick和OnClick的区别? 解答:http://www.cnblogs.com/ypfnet/archive/2012/1 ...
- oracle数据库的备份与还原
转自:https://www.cnblogs.com/ylldbk/p/5613365.html 数据导出: 1 将数据库TEST完全导出,用户名system 密码manager 导出到D:\daoc ...
- pyhive -- thrift.transport.TTransport.TTransportException: TSocket read 0 bytes
Pyhive 远程连接hive出现问题: from pyhive import hive import pandas as pd #Create Hive connection conn = hive ...
- 阿里云服务器mail 命令发邮件
一.申请开通25端口 https://yundun.console.aliyun.com/?spm=5176.2020520001.aliyun_topbar.188.KbmgKc&p=sc# ...
- angularjs的ng-repeat回调
首先html代码是这样的: <label>Name des Leiters:</label><select name="leaderID" id=&q ...