一.MQ
1.MQ介绍
MQ全称为Message Queue,即消息队列。“消息队列”是在消息的传输过程中保存消息的容器。它是典型的:生产者、消费者模型。生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息。因为消息的生产和消费都是异步的,而且只关心消息的发送和接收,没有业务逻辑的侵入,这样就实现了生产者和消费者的解耦。
2.MQ的优缺点
2.1优点:
- 应用解耦
MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合 - 吞吐量提升
整个调用响应时长变短,提升吞吐量 - 故障隔离
下游服务故障,不会影响上游服务 - 流量削峰
高并发的请求数,由Broker来抗,不会直接打到具体的服务,后面可以根据服务的消费能力来慢慢消费
2.2缺点:
-
系统可用性降低
系统引入的外部依赖越多,越容易挂掉。 -
系统复杂度提高
MQ的加入会导致系统复杂度提升,使整体架构变得复杂。
二. RabbitMQ
1.RabbitMQ简介
RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开发中应用非常广泛。
2.RabbitMQ工作原理
下图是RabbitMQ的基本结构:
2.1组成部分说明
- Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue
- Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。
- Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的
- Producer:消息生产者,即生产方客户端,生产方客户端将消息发送
- Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。
2.2流程说明
生产主要负责发送消息,实现步骤具体如下
1.创建连接工厂
2、获取连接
3、创建通道
4、声明队列
5、发送消息
6、关闭通道和连接
消费者主要负责消费消息,实现步骤具体如下:
1、创建连接工厂
2、获取连接
3、创建通道
4、声明队列
5、异步订阅消息
3.消息模型
3.1 基本消息模型
3.1.1 基本模型角色介绍
- P 生产者:发送消息
- Q 消息队列:(红色部分)可以缓存消息;生产者向其中投递消息,消费者从其中取出消息
- C 消费者:消息的接受者,会一直等待消息到来
3.1.2 基本模型特点
消费者的消息确认机制(Acknowlage)
消息一旦被消费者接收,队列中的消息就会被删除。
回执ACK 分两种情况:
- 自动ACK,消息一旦被接收,消费者自动发送ACK
- 手动ACK,消息接收后,不会发送ACK,需要手动调用
选择方式:
- 如果消息不太重要,丢失也没有影响,那么自动ACK会比较方便
- 如果消息非常重要,不容丢失。那么最好在消费完成后手动ACK,否则接收消息后就自动ACK,RabbitMQ就会把消息从队列中删除。如果此时消费者宕机,那么消息就丢失了
3.2 WorkQueue
3.2.1 WorkQueue角色介绍
- P 生产者:发送消息
- Q 消息队列:可以缓存消息;生产者向其中投递消息,消费者从其中取出消息
- C1 消费者:领取任务并完成任务
- C2 消费者2:领取任务并完成任务
3.2.2 WorkQueue特点
负载均衡 (能者多劳)
- 场景:当消息处理比较耗时的时候,当生产消息的速度会远远大于消息的消费速度时,导致消息就会堆积越来越多,无法及时处理。
- 使用work 模型:让多个消费者绑定到一个队列,共同消费队列中的消息。队列中的消息一旦消费,就会消失,因此任务是不会被重复执行的。任务平均分配,消费效率高的,消费的消息也越多。
3.3 Fanout
3.3.1 Fanout角色介绍
- P 生产者:发送消息
- X Exchange(交换机):生产者将消息发送到交换器,交换器根据路由规则将消息路由一个或多个队列中。而路由规则受 Exchange 的类型和绑定(binding) 关系的影响
- 多个消费者,每个消费者都有自己的消息队列Queue,每个消费者将自己的Queue绑定到自己感兴趣的Exchage (可以绑定多个Exchange)
3.3.2 Fanout特点
fanout exchange 会将消息分发给所有绑定到此 exchange 的queue中,不管 queue中的 route key。如果有 N 个 Queue 绑定到 一个 fanout exchange 时,那么此时 exchange 收到消息时,会将此消息分发到 这 N 个 queue中,由于此性质, fanout exchange 也常用消息的广播。
3.4 Direct
direct exchange 根据消息携带的 routing key 将消息投递到不同的 queue中,direct exchange 适用于消息的单播发送。工作流程如下:
- 将一个队列绑定到某个交换机上,同时赋予该绑定 一个 route key。
- 当一个携带 route key为R 的消息被发送到 direct exchange 时,exchange 会将消息路由到 绑定值同样为 R 的队列。注意Route Key和绑定值要完全匹配才行。
direct exchange 经常用于在 多个 worker 中分配任务,当这样做时,需注意,在AMQP 0-9-1中,息的负载均衡发生在 consumer之间,而不是在 queue之间。
3.5 Topic
topic exchange 会根据 route key 将消息分发到与此消息的 route key 相匹配的并且绑定此exchange的一个或多个 queue。这里的**“相匹配”**与 direct exchange的完全匹配的路由规则不一样,topic exchange 在匹配规则上进行了扩展,规则如下:
- RoutingKey(路由键)为一个点号 “.” 分隔的字符串
- BindingKey(绑定键) 和 RoutingKey一样也是点号 “.” 分隔的字符串
- BindingKey (绑定键) 中可以存在两种 特殊字符串 “*” 和 “#” ,用于做模糊匹配,其中 " # " 用于匹配一个单词," * "用于匹配多个单词
topic exchange 经常用于实现 publish/subscribe模型,即消息的多播模型。前面介绍消息模型也曾提到过消息中间件一般有两种模式:点对点模式和发布/订阅模式。这里的Topic Exchange就适用于发布/订阅模型。RabbitMQ的一个原则就是,消息不能直接投递到 Queue中,必须先将消息投递到 Exchange中,然后由Exchange 按照路由规则将消息投递到对应的 Queue中。至于点对点模型就可以用 Direct Exchange来实现,利用完全匹配的路由规则。