文章目录
- 消息队列
- 消息队列
- 消息队列的作用
- 图解生产者消费者模型
- BrokerSever 内部涉及的关键概念
- 交换机功能
- 消费的实现方式
- 数据存储方式
- 网络通信
- 消息应答模式
消息队列模拟实现Gitee网址
消息队列
采用 SpringBoot 框架实现
消息队列
通常说的消息队列,简称MQ(Message Queue),指的就是消息中间件。简单理解为一个使用阻塞队列来通信的组件,本质上就是个转发器,包含发消息,存消息,消费消息的过程。他是一种⽣产者消费模型 (进程和进程之间/服务和服务之间)
消息队列的作用
- 解耦合
- 本来有个分布式系统,A服务器 调⽤ B服务器(A给B发请求,B给A返回响应)===》 A 和 B 的耦合是⽐较⼤的!
- 引⼊消息队列后,A把请求发送到消息队列,B再从消息队列获取到请求,将 A 与 B 之间的耦合程度降低(追求高内聚、低耦合)
- 削峰填⾕
- ⽐如A是⼊⼝服务器,A 调⽤ B 完成⼀些具体业务,如果是 A 和 B 直接通信,如果突然A 收到⼀组⽤户的请求的峰值,此时 B 也会随着受到峰值~
- 引⼊消息队列后,A把请求发送到消息队列,B再从消息队列获取到请求。 (虽然A收到很多请
求,队列也收到了很多请求,但是B仍旧可以按照原来的节奏处理请求。不⾄于说⼀下就收到太
多的并发量而导致服务器 B 奔溃)
图解生产者消费者模型
结合实际,我们多使用消息队列在分布式系统中,一对一或者一对多的关系无法满足我们服务器对于消息队列的需求,因此以多对多的方式来实现
BrokerSever 内部涉及的关键概念
- 虚拟主机(Virtual Host):可以看做一个“逻辑”上的数据集合
- 交换机(Exchange):生产者把消息投递到 BrokerSever 实际上是先把消息交给 BrokerSever 上的某个交换机,再有交换机把消息转发给对应的队列(类似“前台”)
- 队列(Queue):真正用来存储处理消息的实体后续消费者也是从对应的队列中去数据,大队 列中也可以有很多小的队列
- 绑定(Bingding):把交换机和队列建立起关联关系(交换机和队列视为“多对多”关系)
- 消息(Message):具体来说,可以认为是服务器 A 给 B 发的请求(通过MQ转发)就是一个消息,服务器 B 给 A 返回的响应,,也可看做是一个消息,消息可以视为一个字符串(二进制数据)
交换机功能
交换机类型:用于描述不同的转发规则
1 Direct 直接交换机:
- 生产者发送消息的时候会指定一个“目标队列”的名字
- 交换机收到以后就看看绑定的队列里有没有匹配的队列~
- 如果有,转发过去(把消息塞进对应的队列中)如果没有则直接丢弃
2 Fanout 扇出交换机:
- 把消息放到交换机绑定的每个队列
- 只要和这个交换机绑定任何队列都会转发消息
3 Topic 主题交换机:
- bindingKey.把队列和交换机绑定的时候,指定一个单词,暗号~
- routingKey.生产者发送消息时,也指定一个单词
- 如果 bindingKey 和 routingKey 对上暗号~~此时就可以把这个消息转发到对应的队列中
消费的实现方式
此处采用 推 的实现方式:Broker把收到的数据主动发送给订阅的消费者(订阅:哪些消费者要从中间人这里取数据,这个注册的过程,称为“订阅”)
数据存储方式
数据的存储主要有两点需要注意:持久化 + 高效,因此采用 内存 + 硬盘 的方式来存储
- 内存:高效的转发处理数据,效率高
- 硬盘:防止在内存中的数据随着进程重启/主机重启而丢失
网络通信
此处的目的是让客户端通过网络调用 BrokerSever 提供的编程接口,采用 TCP + 自定义的应用层协议 来实现生产者/消费者模型,如下图解所示:
消息应答模式
根据需求不同,此处有两种方式实现消息应答:
- ⾃动应答,消费者把这个消息取⾛了,就算应答了
- ⼿动应答,basicAck ⽅法属于⼿动应答(消费者需要主动调⽤这个 API 来进⾏应答)