RabbitMQ
RabbitMQ
ShioRabbitMQ初体验
🚧🚧🚧 暂待施工🚧🚧🚧
初识MQ
同步调用的优缺点
同步通讯与异步通讯
同步调用的时效性高
同步调用的问题
总结
同步调用的优点
- 实时性好, 时效性高
同步调用的缺点
- 耦合高, 系统需求更改导致维护, 更改困难
- 性能吞吐量下降, 线性调用, 每次调用都要阻塞等待服务方响应, 导致性能下降
- 资源浪费, 调用链每个服务都要等待响应过程, 无法释放请求占用的资源
- 级联失败, 服务提供方出问题,所有调用方都会出问题, 多米诺骨牌
异步调用的优缺点
异步调用方案
优势一 服务解耦
采用发布订阅模式, 支付服务只负责发布事件至Broker, 而其他服务只负责订阅相应的Broker
实现了, 服务调用方和提供方的解耦
假如, 需求发生变化, 需要在支付成功事件后添加其他服务, 只需要添加相应的服务, 并让该服务订阅相应的事件(支付成功事件)
假如, 需求又发生变化, 需要在支付成功事件后取消短信服务, 只需要让该服务(短信服务)取消订阅相应的事件即可
优势二 : 性能提升, 吞吐量提高
采用 同步调用方案 最后耗时将会是 所有服务耗时之和 即 50 + 10 + 150 + 150 + 150 = 510 ms
采用 异步调用方案 最后耗时则只是 支付服务和发布支付时间(不需要阻塞)之和 即 50 + 10 = 60 ms
同时调用方不需要阻塞等待也避免的了资源浪费问题
优势三 无级联失败风险
即使仓储服务挂了, 也并不影响其他服务的正常调用, 只需让仓储服务重启重新读取消息即可,
不会导致级联失败
优势四 流量消峰
就像洪水爆发时, 大坝蓄洪一样, 对于激增请求量, 使用队列存储起来, 让服务提供方按照正常的速度消费存储下的消息, 避免因请求激增导致服务压力过载崩掉
**总结: **
异步通信的优点:
- 耦合度低
- 吞吐量高
- 故障隔离
- 流量削峰
**异步通信的缺点: **
- 依赖于Broker的可靠性, 安全性, 吞吐能力
- 架构复杂, 业务没有明显的流程线条, 不好追踪管理
消息队列
MQ ( MessageQueue ), 中文是消息队列,字面来看就是存放消息的队列。也就是事件驱动架构中的Broker。
RabbitMQ | ActiveMQ | RocketMQ | Kafka | |
---|---|---|---|---|
公司社区 | Rabbit | Apache | 阿里 | Apache |
开发语言 | Erlang | Java | Java | Scala & Java |
协议支持 | AMQP, XMPP, SMTP, STOMP | OpenWire, STOMP, REST, XMPP, AMQP | 自定义协议 | 自定义协议 |
可用性 | 高 | 一般 | 高 | 高 |
单机吞吐量 | 一般 | 差 | 高 | 非常高 |
消息延迟 | 微秒级 | 毫秒级 | 毫秒级 | 毫秒以内 |
消息可靠性 | 高 | 一般 | 高 | 一般 |
RabbitMQ快速入门
RabbitMQ是基于Erlang语言开发的开源消息通信中间件,官网地址:https://www.rabbitmq.com
常见消息模型
RabbitMQ 官方文档中提供了 5个Demo, 对应了几种不同的用法:
BasicQueue
总结
基本消息队列的消息发送流程
创建并配置
ConnectionFactory
从
ConnectionFactory
获取Connection
利用
Connection
创建channel
利用
channel
声明队列利用
channel.basicPublish()
向队列中发送消息
基本消息队列的消息接受流程
创建并配置
ConnectionFactory
从
ConnectionFactory
获取Connection
利用
Connection
创建channel
利用
channel
声明队列定义
consumer.basicConsume()
的消费行为handleDelivery()
利用
channel
将消费者与队列绑定
SpringAMQP
什么是SpringAMQP
Work Queue
消息预取机制(preFetch)
Work模型的使用总结
- 多个消费者绑定到一个队列,同一条消息只会被一个消费者处理
- 通过设置prefetch来控制消费者预取的消息数量
发布订阅模式
发布(Publish), 订阅(Subscribe)
发布订阅模式与之前案例的区别就是允许将同一消息发送给多个消费者。实现方式是加入了exchange
(交换机)。
常见的exchange
包括
Fanout
: 广播Direct
: 路由Topic
: 话题
发布订阅- Fanout Exchange
FanoutExchange会将接收到的消息路由到每一个跟其绑定的queue
总结
交换机的作用是什么?
- 接收
publisher
发送的消息 - 将消息按照规则路由到与之绑定的队列
- 不能缓存消息,路由失败,消息丢失
FanoutExchange
的会将消息路由到每个绑定的队列
声明队列, 交换机, 绑定关系的Bean是什么?
- Queue
- FanoutExchange
- Binding
发布订阅- Direct Exchange
Direct Exchange
会将接收到的消息根据规则路由到指定的Queue
,因此称为路由模式(routes)。
- 每一个
Queue
都与Exchange
设置一个BindingKey
- 发布者发送消息时,指定消息的
RoutingKey
Exchange
将消息路由到BindingKey
与消息RoutingKey
一致的队列
还可以绑定多个key, 多个Queue
绑定同一个key, 就实现了Fanout Exchange
的效果, 所以说Direct Exchange
更灵活一些
描述下Direct交换机与Fanout交换机的差异?
Fanout
交换机将消息路由给每一个与之绑定的队列Direct
交换机根据RoutingKey
判断路由给哪个队列- 如果多个队列具有相同的
Routing Key
,则与Fanout
功能类似
基于RabbitListener
注解的声明队列与交换机有哪些常见的注解?
@QueueBanding
@Queue
@Exchange
发布订阅- Topic Exchange
Topic Exchange
与Direct Exchange
类似,区别在于routing Key
必须是多个单词的列表,并且以**.
**分割
Queue
与Exchange
指定的BindgingKey
时可以使用通配符:
#
代表0个或多个单词*
代表一个单词
消息转化器
Spring
的对消息对象的处理是由org.springframework.amqp.support..converter.MessageConverter
来处理的。而
默认实现是SimpleMessageConverter
,基于JDK的ObjectOutputStream
完成序列化。
SpringAMQP中消息的序列化和反序列化是怎么实现的?J
- 利用
MessageConverter
实现的,默认是JDK的序列化 - 注意发送方与接收方必须使用相同的
MessageConverter