消息中间件-RabbitMQ
RabbitMq
为什么要写RabbitMQ,首先消息中间件在现在的web开发中担当着非常重要的角色,特别是微服务的流行,在处理各个服务间数据异步交互非常有效。
当时接触的第一个消息中间件也是RabbitMQ。写这篇文字一是对之前的知识做一个总结,由于能力有限,没法从源码到实现细节做较多的分析,主要也是
作为一种知识笔记,在后面可以直接通过该文章作为认知参考。以下内容会根据对RabbitMQ的不断认识与应用不断总结。
服务端使用版本号:3.7.8。
介绍
RabbitMQ是轻量级的,易于部署在本地或云环境中。 它支持多种消息传递协议。 RabbitMQ可以部署在分布式和联邦配置中,以满足大规模、高可用性的需求
都说rabbitmq基于erlang语言实现,先天有处理的高并发的优势
支持的语言非常丰富:
JAVA
.NET
Ruby
Python
PHP
Javascript
Go
Rust
...
支持多种协议:
AMQP
STOMP
MQTT
HTTP
WebSocket
...
特色
- Asynchronous Messaging :支持多种协议的异步消息
- Developer Experience : 支持多语言
- Distributed Deployment :支持分布式部署
- Enterprise & Cloud Ready :可插拔的认证授权机制,轻量级云部署
- Tools & Plugins : 多种工具和插件支持企业持续集成
- Management & Monitoring :http、命令管理以及UI界面实现管理和监控
名词
| 名称 | 描述 |
|---|---|
| broker | 中间件 |
| connection | 连接:与rabbitMq通信必须先建立连接,rabbit基于amqp协议,顶层仍是通过tcp进行数据传输 |
| channel | 通道:一个连接可以有多个通道,实现连接复用,减少多个连接对资源的浪费 |
| vhost | 虚拟主机:实现了数据在逻辑上的隔离 |
| exchange | 交换机:消息都是先交换机,根据交换机与队列的bindingKey实现消息的分发 |
| queue | 队列:消息的载体 |
- exchange声明参数
name: 交换机名称
type: fanout|direct|topic|headers
durable: 是否持久性
autoDelete: 是否自动删除
internal: 是否内部交换机。如果true,则不能通过客户端直接使用,只能通过交换路由(channel.exchangebind)的形式使用
arguments: 交换机参数
-
参数名 参数说明 alternate-exchange 配置备用交换机,当发送到交换机的消息路由到任何队列时,则会将消息发布到指定的备用交换机上
- queue声明参数
durable 持久性?是否在服务器重启后保留该队列
exclusive 独占队列?是否在一个连接内被锁定,注意是在一个连接而不是一个通道上。包含autoDelete特性
autoDelete 自动删除?不再使用是自动删除,生产与消费端都断开了连接
arguments 参数?\
-
参数名 参数说明 x-message-ttl 队列内消息存活时间(TTL),如果超过该时间,且配置DLX则消息会发送到死信队列中,否则丢弃 x-expires 队列存活时间 x-max-length 队列中消息最大数量,超过时删除之前的消息 x-max-length-bytes 队列中消息占用内存大小,超过时删除之前的消息 x-dead-letter-exchange 死信交换机名称(DLX) x-dead-letter-routing-key 死信routingKey x-max-priority 队列支持的最大优先级,1 到 255 之间的正整数 x-queue-mode lazy,尽可能早地将消息移动到磁盘,消息在消费时才会被加载到内存中 x-queue-master-locator min-masters/client-local/random,集群时让队列领导可以使用多种策略分布在节点之间 -
消息发布参数
mandatory: 为true时,当交换机没有匹配到路由时,消息被return;否则消息丢弃
immediate: 为true时,如果队列有关联消费者则消费,否则消息被return;否则消息不处理 ?
properties: 消息属性
-
参数名 参数说明 contentType 消息类型 contentEncoding 消息编码 headers 消息头,headers模式可以用到 deliveryMode 传输模式,写入内存或磁盘 priority 优先级,x-max-priority相关 correlationId 关联id replyTo rpc时用到 expiration 过期时间 messageId 消息id timestamp type userId appId clusterId 集群id
应用场景
应用解耦
异步业务
流量削峰
RPC
延迟业务
负载均衡
EXCHANGE
-
fanout
广播,将消息发送到所有与交换机绑定的队列上 -
direct
将消息发送到与交换机routingKey匹配的队列上
与fanout的区别,如果有多个消费者,fanout交换机会把消息发送到每一个消费者上,而direct不会 -
topic
将消息发送到与交换机routingKey匹配的队列上,基于routingKey和bindingKey,支持通配符匹配 -
headers
基于消息properties进行批量
示例情形

简单地实现消息生产与消费

多个消费者订阅一个消息队列,完成消息均匀消费的目的,实现消息的分发

基于fanout交换机,实现将消息完整地发布到与之绑定的所有队列上,实现发布订阅模式

基于direct交换机,根据消息发布key与队列绑定key相同,按业务类型实现消息的定向分发

基于topic交换机,根据消息发布key与队列绑定key的匹配规则,按业务类型实现消息的定向分发

基于消息队列的RPC
消息生产
-
可靠性
-
如何确保消息发送成功?
- 消息发送到exchange
- 消息发送到queue
-
rabbitmq如何实现?
- 事务机制 (TX)
- 发送确认机制 (ACK)
-
-
重试策略
-
消息没有发送到中间件
- 可基于类似于spring-retry这样的框架,重复发送
-
消息发送到中间件失败
- 基于消息发送回调
- 基于定时重试策略
-
-
死信
- 条件
- 消息被拒绝(Basic.Reject/Basic.Nack) ,井且设置requeue 参数为false
- 消息过期
- 队列达到最大长度
- 条件
消息消费
- 重复消费
-
主要是在业务上的重复
- 不同业务
- 同一业务不同状态,由于消息消费顺序导致后发送的消息先被消费
-
中间件层面的重复
- 因为网络或其他原因导致消息的重复发送或重传消费
-
问题
-
消息的有序性
消息的优先级,只能在一定 程度上实现消息消费顺序,无法保证消息的逻辑上的顺序
-
消息积压
消息的生产与消费不均衡
注意事项
1、根据路由规则,消息会全部发送到匹配的队列上,但是同一个队列上多个消费者会不重复消费所有消息
2、autoDelete并不是简单的队列没有生产或订阅就会被删除,比如生产者往队列里生产消息,但是该队列至始至终都没有过消费者订阅,那么就算生产者断开了,
队列一样不会自动删除

浙公网安备 33010602011771号