RabbitMQ
1.RabbitMQ总结
2. AMQP是什么?
- AMQP(高级消息队列协议)是一个网络协议。它支持符合要求的客户端应用(application)和消息中间件代理(messaging middleware broker)之间进行通信。
2.1 消息代理和他们所扮演的角色?
- 消息代理(message brokers)从发布者(publishers)亦称生产者(producers)那儿接收消息,并根据既定的路由规则把接收到的消息发送给处理消息的消费者(consumers)。由于AMQP是一个网络协议,所以这个过程中的发布者,消费者,消息代理 可以存在于不同的设备上。
3. MQ是什么?
- Message Queue 消息队列
- MQ是用来传输Message的中间载体,称为消息中间件。
4. 常见的消息中间件有哪些?
- ActiveMQ : SUN公司提供的规范
- RabbtiMQ:常用
- RocketMQ:阿里
- kafka:常用(最初设计目的是用来完成分布式下日志的收集)
5. 消息中间件有什么用?
- 流量削峰(解决高并发问题)
- 串行化请求:将所有的并行请求进行串行化(放进队列里)
- 消息分发
- 消息缓冲
- 监控消息
- 异步处理:异步推送消息,异步发送短信,日志处理
- 模块之间的异步通信(解耦,模块之间没用相互依赖关系)
6. RabbtiMQ的消息状态有哪些?
- Ready:等待被消费状态
- Unacked:未确认状态,消息投递到消费者,消费者没有应答
7. RabbtiMQ的核心组件有哪些?
-
Broker:RabbtiMQ服务器实体
-
exchange:消息交换机,处理消息和队列之间的关系
- fanout(扇形交换机):该类型会把发送到交换机的消息直接推送给与之绑定的队列上(广播)。
- direct(直连交换机):该类型会把发送到交换机并且携带路由key的消息推送给与该路由key匹配的队列上。
- topic(主题交换机):直连交换机的升级版,新增了路由key模糊匹配规则。队列可使用* #去匹配消息。
-
queue:消息队列
-
TTL属性:Time To Live ,可以设置队列中消息的过期时间
-
DLX属性:死信属性,可以指定队列中过期消息的回收交换机
Map<String,Object> map=new HashMap<>(); //添加ttl属性,设置队列消息过期时间为5秒 map.put("x-message-ttl",5000); //添加死信的属性,指定死信交换机 map.put("x-dead-letter-exchange",DLX_EXCHANGE_NAME); channel.queueDeclare(QUEUE_NAME,true,false,false,map);
-
-
binding:绑定,把队列和交换机按照路由规则绑定起来。
-
Routing Key:路由匹配钥匙,交换机根据路由key投递消息到队列。
-
producer:生产者,生成消息的程序。
-
consumer:消费者,消费消息的程序。
-
virtualHost: 虚拟消息服务器,每个virtualHost相当于一个相对独立的MQ服务器,每个virtualHost之间是相互隔离的。交换机,队列和消息不能互通
-
channel:消息通道,是建立在真实TCP连接之上的虚拟连接。
-
confirm机制:RabbitMQ服务器确认消息是否到达交换机的机制,每次生产者发送消息到交换机都会进行确认。
-
return机制:RabbitMQ服务器确认消息是否从交换机到达队列的机制,没到达会触发。
8. RabbtiMQ的消息被可靠持久化的条件是什么?
-
队列和交换机都设置为持久化(durable 属性),同时消息设置为持久化(persistent 属性)
-
如果队列或者交换机没有设置持久化,RabbitMQ服务器重启就会丢失队列和交换机。
## 第三个参数MessageProperties.PERSISTENT_TEXT_PLAIN表示这条消息持久化
channel.basicPublish(
EXCHANGE_NAME,
ROUTING_KEY,
MessageProperties.PERSISTENT_TEXT_PLAIN,
message.getBytes(StandardCharsets.UTF_8)
);
9. RabbitMQ的通信模型有哪些?
9.1 helloWord模型
[Producer]--->[Message queue]--->[consumer]
9.2 Work模型
[Producer]--->[Message queue]--->[consumer1,consumer2]
[消费者1的数据] + [消费者2的数据] = [原消息队列的所有数据]
9.3 Publish模型(发布订阅模型 )
- 使用交换机类型:fanout(扇形交换机)
- 可称为广播模式:消息队列订阅了交换机,交换机将消息广播到2个消息队列,交换机相当于广播。
- 消费者1的数据 = 消费者2的数据 = 队列1的数据 = 等于队列2的数据 =交换机的数据。
[Producer]--->[Exchange]--->[Message queue...]--->[consumer...]
9.4 路由模型
- 路由模型相当于是发布订阅模式的升级版,增加了根据路由key投递消息到指定队列的机制
- Receiving messages selectively:可以理解为队列选择性的接收交换机消息
- 使用的交换机类型:direct直连型交换机
9.5 主题模型Topics
- 是路由模型的升级版,增加了队列模糊匹配接收消息的机制
- Receiving messages based on a pattern :可以理解为队列根据模糊匹配规则接收消息
- 使用的交换机类型:topic主题交换机
(xxx.*, xxx.#, #)
* 能够代表一个单词: 如消息指定的路由key是dlx.save或者dlx.delete 队列的路由key是
dlx.*就可以匹配上
#可以代表多个单词: 如消息指定的路由key是dlx.save.one 队列的路由key是dlx.#这样就可以匹配上
如果声明队列的路由key为单个#的话,可以匹配任何路由key,换句话说可以接收交换机上的任何消息
10. RabbitMQ的高可用
11. 消费者端 手动签收 和 消息的重回队列?
- 场景:当消费者端接收到了队列中数据,但是在进行业务逻辑处理的时候发生异常?
- 为了应对这种情况:需要我们自己手动应答,出了异常就要手动拒绝并让消息重回队列
//手动签收
//param1:当前接收到的消息的唯一标识
//param2:是否批量应答
channel.basicAck(envelope.getDeliveryTag(),false);
//手动拒绝签收
//param1:当前接收到的消息的唯一标识
//param2:是否批量应答
//param3:是否让消息重回队列
channel.basicNack(envelope.getDeliveryTag(),false,true);
//手动拒绝单条消息,并重回队列
channel.basicReject(envelope.getDeliveryTag(), true)
N. 如何保证消息的可靠性传输?
-
消息的延迟投递来解决传递的可靠性
-
日志消息表实现可靠消息的传输