在介绍RabbitMQ之前,我们先来看下面一个电商项目的场景:
如果我们在后台修改了商品的价格,搜索页面和商品详情页显示的依然是旧的价格,这样显然不对。该如何解决?
我们可能会想到这么做:
这两种方案都有个严重的问题:就是代码耦合,后台服务中需要嵌入搜索和商品页面服务,违背了微服务的独立原则。
这时,我们就会采用另外一种解决办法,那就是消息队列!
商品服务对商品增删改以后,无需去操作索引库和静态页面,只需向MQ发送一条消息(比如包含商品id的消息),也不关心消息被谁接收。 搜索服务和静态页面服务监听MQ,接收消息,然后分别去处理索引库和静态页面(根据商品id去更新索引库和商品详情静态页面)。
RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、 安全。AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。RabbitMQ是一个消息代理:它接受和转发消息。 你可以把它想象成一个邮局:当你把邮件放在邮箱里时,你可以确定邮差先生最终会把邮件发送给你的收件人。 在这个比喻中,RabbitMQ是邮政信箱,邮局和邮递员。
RabbitMQ与邮局的主要区别是它不处理纸张,而是接受,存储和转发数据消息的二进制数据块。
MQ全称为Message Queue,即消息队列。
消息队列(MQ)是一种应用程序对应用程序的通信方法。
应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。
消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。
排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。“消息队列”是在消息的传输过程中保存消息的容器。它是典型的:生产者、消费者模型。生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息。因为消息的生产和消费都是异步的,而且只关心消息的发送和接收,没有业务逻辑的侵入,这样就实现了生产者和消费者的解耦。
组成部分说明:
生产者:
(1) 生产者连接到RabbitMQ Broker,建立一个连接( Connection)开启一个信道(Channel)
(2) 生产者声明一个交换器,并设置相关属性,比如交换机类型、是否持久化等
(3) 生产者声明一个队列井设置相关属性,比如是否排他、是否持久化、是否自动删除等
(4) 生产者通过路由键将交换器和队列绑定起来
(5) 生产者发送消息至RabbitMQ Broker,其中包含路由键、交换器等信息。
(6) 相应的交换器根据接收到的路由键查找相匹配的队列。
(7) 如果找到,则将从生产者发送过来的消息存入相应的队列中。
(8) 如果没有找到,则根据生产者配置的属性选择丢弃还是回退给生产者
(9) 关闭信道。
(10) 关闭连接。
消费者:
(1) 消费者连接到RabbitMQ Broker ,建立一个连接(Connection),开启一个信道(Channel) 。
(2) 消费者向RabbitMQ Broker 请求消费相应队列中的消息,可能会设置相应的回调函数,
(3) 等待RabbitMQ Broker 回应并投递相应队列中的消息,消费者接收消息。
(4) 消费者确认(ack) 接收到的消息。
(5) RabbitMQ 从队列中删除相应己经被确认的消息。
(6) 关闭信道。
(7)关闭连接。
在上图的模型中,有以下概念:
P:生产者,也就是要发送消息的程序
C:消费者:消息的接受者,会一直等待消息到来。
queue:消息队列,图中红色部分。可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。
不用显示声明交换机,只需声明一个队列
生产者指定队列名发送消息给MQ,然后会有一个默认的交换机将消息转发给这个队列。
消费者负责监听这个队列,一有消息就会得到通知做出响应。
和简单队列模式基本一样,不过有一点不同,该模式有多个消费者在监听队列。
RabbitMQ会以轮询的方式将消息发给多个消费者确保一条消息只会被一个消费者消费
和上面2种模式默认提供交换机不同的是,该模式需要显示声明交换机,
然后可以创建多个队列和这个交换机进行绑定。
生产者发消息给mq时需要指定交换机,然后交换机将消息转发给与自己绑定的所有队列
消费者监听指定的队列获得消息。每个队列可以有多个消费者监听,同样也是以轮询的机制发给消费者。
和发布订阅模式不同的是,队列绑定交换机时需要指定一个routingkey
那么生产者发送消息时不仅需要指定交换机还需要指定routingkey
这样的话交换机就会把消息转发给跟自己绑定并且routingkey相匹配的队列
和Routing模式唯一的不同就是可以设置带有通配符进行模糊匹配的routingkey
和Routing模式的不同就是取消了routing 使用键值对的方式作为routing