欢迎关注 公众号 dying 搁浅 有音频版本
MQ 全拼 Message Queue 即 消息队列。是在消息的传输过程中保存消息的容器,多用于分布式系统。
MQ 所带来的优势即我们用 MQ 的理由,如下:
实际案例场景:
秒杀、聊天、等
所谓 天下没有免费的午餐,有利就有弊,引入 MQ 同样也会给我们带来不少问题:
利弊权衡间考虑你的系统是否需要引入消息队列。
公司/社区: Rabbit
开发语言:Erlang (为高并发和分布式诞生的语言,电信领域使用广泛)
协议支持:AMQP、XMPP、SMTP、STOMP
客户端支持语言:官方支持 Erlang、Java、Ruby 等,社区提供几乎支持所有主流语言。
单机吞吐量: 万级
消息延迟: 微秒
功能特性:并发能力强,性能极好,低延迟,社区活跃,完善的管理界面。
AMQP 全称 Advanced Message Queuing Protocol 即 高级消息队列协议,是一个应用层网络协议,专门面向消息队列的中间件进行设计的协议。基于此协议的客户端与消息中间件可以传递消息,不受不同 客户端/中间件/开发语言等条件限制。是一个通信规范。
Broker: 中间件,接收和分发消息的应用,如 RabbitMQ Server 就是 Message Broker (消息中间件)
Virtual host:虚拟主机,出于多租户和安全的考虑,把 AMQP 的基本组件划分到一个虚拟的分组中,类似于网络中 namespace 命名空间的概念。当多个用户使用同一个 RabbitMQ server 所提供的服务时,可以划分出多个 virtual host ,每个用户在自己的 virtual host 进行 exchange 以及 queue 等,互不干扰。
Connection 链接,publisher 发布者 、consumer 订阅者 与 broker 之间的 TCP 链接。
Channel:通道,管道。 channel 是在 connection 内部建立的逻辑链接,为了避免程序多线程而创建多个 connection 做的优化。 如果应用程序支持多线程,通常每个 thread 会创建单独的 channel 进行通讯, AMQP Method 包含了 channelId 帮助客户端和 message broker 识别 channel ,每个 channel 相互隔离。这个概念有点类似 进行和线程的对应关系,正好一个进程对应一个 connection ,一个线程对应一个 channel 这样的感觉。
Exchange:交换机,message 到达 broker 会先进过 交换机 ,根据分发规则,查表匹配 routing key ,将消息分发到对应的 queue。常用的类型: direct (point-to-point),topic(publish-subscribe)、fanout (multicast)后文会详细说明。
Queue:队列,消息最终存储位置,等待 consumer 消费。
Binding: exchange 与 queue 之间的虚拟链接,binding 中可以包含 routing key。binding 信息被保存到 exchange 的查询表中,用于消息的分发。
https://www.rabbitmq.com/getstarted.html
这个模式简单理解就是 一对一的消费模式,一个生产者对应一个消费者,消息仅消费一次。
工作队列模式,与上面的简单模式区别是 可以多个生产者,然后由多个消费者一起消费消息,消息仅消费一次,对应的可以提高消息的处理速度。
到这里,发布订阅模式,路由模式,主题模式 其实结构上大同小异,区别仅仅是 交换机 Exchange 的绑定路由规则不同罢了。
同时在该模式下,一份消息会分发给符合条件的多个队列使用,且比上面的模式多了交换机的概念。
交换机 顾名思义 作用就是将生产者生产的消息,根据一定的规则分发到对应的队列中。
发布订阅模式的 Exchange 交换机是 Fanout 广播模式,即:将消息交给所有绑定到交换机的队列
路由模式的 Exchange 交换机是 Direct 定向模式,即:把消息交给 routing key 路由对应的队列
主题模式的 Exchange 交换机是 Topic 通配符模式,即:把消息交给 routing pattern 路由匹配的队列
RPC 不是消息队列的重点,这里不做过多解释。RPC 有更多成熟的框架实现,个人不建议使用消息队列来实现。
在使用 RabbitMQ 的时候,作为消息发送方希望杜绝任何消息丢失或者投递失败场景。RabbitMQ 为我们提供了两种方式用来控制消息的投递可靠性模式。
confirm 确认模式
return 退回模式
rabbitmq 整个消息投递的路径为:
producer—>rabbitmq broker—>exchange—>queue—>consumer
消息从 producer 到 exchange 投递失败会返回一个 confirmCallback 。
消息从 exchange–>queue 投递失败会返回一个 returnCallback 。
我们将利用这两个 callback 控制消息的可靠性投递
注意这两个模式需要进行配置开启。如:
publisher-confirms=“true” 确认模式开启
publisher-returns=“true” 回退模式开启
RabbitMQ 在消费端提供了 3 种确认机制
无需确认 acknowledge = "none"
该模式下无需手动编写代码 ack 。RabbitMQ 默认 consumer 正确处理所有请求。
手动确认 acknowledge="manual"
该模式下需要手动编写代码进行消息确认 如正常收到消息 channel.basicAck()
消息异常 channel.basicNack()
等。
自动确认 acknowledge="auto"
consumer 自动应答,处理成功(即没有发生异常)发出 ack,处理失败发出 nack。queue 发出消息后会等待 consumer 端应答,只有收到 ack 确定信息后才会将消息在 queue 中清除掉。收到 nack 异常信息的处理方法由setDefaultRequeueReject() 方法设置,这种模式下,发送错误的消息可以恢复。
关于 Java 代码编写使用上,一般有 三种 方式
纯 Java 代码方式
Spring 配置方式
Spring Boot 自动配置方式