为什么要做这样一个项目?
首先,我们在之前学习的时候,就认识了一下 生产者消费者模式,这样一个模式有两大好处:
队列可以说是一个数据结构,可以存储数据,如下图,我们从右侧(队尾)插入元素(入队),从队头获取元素(出队)。

了解了队列之后,我们来看一下什么是消息队列,消息队列就是我们常说的MQ,英文叫Message Queue,是作为一个单独的中间件产品存在的,独立部署。

我们先前已经提过了 解耦合 、 削峰填谷 ;除此之外还有一个好处 : 异步,关于这个异步,等到正式介绍的相关代码我再来细说,这里就不多介绍了。
本项目是 基于 RabbitMQ 实现的较为简易的(所谓建议的意思就是还可以继续完善) MQ;RabbitMQ 是一款比较 “ 年长 ” 的消息队列,比较经典,所以选择了这一款消息队列。
一个生产者,一个消费者

多个生产者,多个消费者


关于持久化,上述 虚拟机、交换机、队列、绑定、消息,需要存储起来,光是存内存显然是不够的(为啥不够呢?万一服务器宕机了,我们消息还没有处理,所以还需要将消息恢复一下),所以我们还需要存硬盘,这里以内存为主、硬盘为辅。
关于存硬盘,我们这里要进行一个区分 :
在内存中存储的原因:
对于 MQ 来说,能够⾼效的转发处理数据,是⾮常关键的指标! 因此对于使⽤内存来组织数据,得 到的效率,就⽐放硬盘要⾼很多
在硬盘中存储的原因:
为了防⽌内存中数据随着进程重启/主机重启⽽丢失
- 创建队列(queueDeclare)
- 此处不⽤ Create这样的术语,原因是Create仅仅是创建;⽽ Declare 起到的效果是,不存在则创建,存在就啥也不做
- 销毁队列(queueDelete)
- 创建交换机(exchangeDeclare)
- 销毁交换机(exchageDelete)
- 创建绑定(queueBind)
- 解除绑定(queueUnbind)
- 发布消息(basicPublish)
- 订阅消息(basicConsume)
- 确认消息(basicAck)
- 这个API起到的效果,是可以让消费者显式的告诉 broker server,这个消息我处理完毕了,提⾼ 整个系统的可靠性~保证消息处理没有遗漏
- RabbitMQ 提供了 肯定 和 否定的 确认,此处我们项⽬就只有 肯定确认
交换机在转发消息的时候,有一套转发规则的
消息队列提供了几种不同的 交换机类型(ExchangeType) 来描述这里不同的转发规则
RabbitMQ主要实现了如下四种交换机(也是由 AMQP协议定义的)
而在我们手写的交换机只实现了前三种:
a. ⽣产者发送消息时,会指定⼀个"⽬标队列"的名字(此时的 routingKey就是 队列的名字)b. 交换机收到后,就看看绑定的队列⾥⾯,有没有匹配的队列c. 如果有,就转发过去(把消息塞进对应的队列中)d. 如果没有,消息直接丢弃

a. 会把消息放到交换机绑定的每个队列b. 只要和这个交换机绑定任何队列都会转发消息

a. bindingKey:把队列和交换机绑定的时候,指定⼀个单词(像是⼀个暗号⼀样)b. routingKey:⽣产者发送消息的时候,也指定⼀个单词c. 如果当前 bindingKey 和 routingKey 对上了,就可以把消息转发到对应的队列

- 专属红包 ======== 直接交换机
- 发个10块钱红包,⼤家都能领 10块钱红包 ======== 扇出交换机
- 我发个⼝令红包,只有输⼊对应⼝令才能领导红包 ======== 主题交换机
至于为啥没有实现 header主题头 交换机 ,那是因为 header 的实现规则复杂,并且实用场景少。
其他的服务器(生产者/消费者)通过网络,和咱们的 BrokerServer 进行交互的。
此处设定,使用 TCP + 自定义应用层协议 实现 生产者/消费者 和 BrokerServer 之间进行交互。
应用层协议主要工作:就是让客户端可以通过网络,调用 BrokerServer 提供的编程接口(从而达到看似是生产者远程调用服务器的API)
消息队列服务器(BrokerServer),要提供的核心 API
- 创建队列(queueDeclare)
- 此处不⽤ Create这样的术语,原因是Create仅仅是创建;⽽ Declare 起到的效果是,不存在则创建,存在就啥也不做
- 销毁队列(queueDelete)
- 创建交换机(exchangeDeclare)
- 销毁交换机(exchageDelete)
- 创建绑定(queueBind)
- 解除绑定(queueUnbind)
- 发布消息(basicPublish)
- 订阅消息(basicConsume)
- 确认消息(basicAck)
- 这个API起到的效果,是可以让消费者显式的告诉 broker server,这个消息我处理完毕了,提⾼ 整个系统的可靠性~保证消息处理没有遗漏
- RabbitMQ 提供了 肯定 和 否定的 确认,此处我们项⽬就只有 肯定确认
因此,客户端这边也需要提供上述 API,只有服务器是真正干实事的;客户端只是发送请求、接收响应:

客户端除了提供了上述 9 个方法之外,还需要提供 4个 额外的方法,支撑其他工作
总结

如果还是不太理解的话,可以结合下列思维导图一起理解: