一,MQ的三大特性与缺点
异步: 同步是发出一个调用请求之后,在没有得到结果之前,就不返回,调用者主动等待这个调用结果。异步通信不需要客户端等待,可以减少客户端性能消耗,大大地提升用户的体验。例如A系统向B,C,D三个系统发送消息,如果其中一个失败,那么导致整个逻辑失败。(火车退票为例,增库存,支付接口,系统API通知)
解耦: 降低系统的耦合性,(耦合的意思是模块间的紧密联系,修改一个模块,多个模块都需要修改)A->B,B->C,C->D
削峰: 电商系统中,有一个瞬间流量达到峰值的情况,普通服务器无法支撑百万或者千万级别的并发量。MQ可以先把所有的流量承接下来。
上面说了引入消息队列的一些场景和优点,那么使用消息队列有什么缺点呢?
系统的可用性降低:比如第一个例子,本来好好的调用三个接口,这个时候接入一个消息队列,凑巧消息队列挂掉了,系统不是直接不能用了,崩溃掉了。
系统的复杂性:加入一个消息队列,若是消息丢失怎么办,消息被重复消费了,消息没有按找既定的顺序消费,都会导致系统出问题。
一致性问题:A系统处理完了直接返回成功了,那么用户就以为成功了,实际上,BC消费成功了,D消费失败了,数据就不一致了。
二、RabbitMQ的核心模块与流程
生产者发送消息
1,消息生产者连接到RabbitMQ Broker,建立链接(Connection),在链接(Connection)上开启一个信道(Channel) 2,声明一个交换机(Exchange),并设置相关属性,比如交换机类型、是否持久化等 3,声明一个队列(Queue),并设置相关属性,比如是否排他、是否持久化、是否自动删除等 4,使用路由键(RoutingKey)将队列(Queue)和交换机(Exchange)绑定起来 5,生产者发送消息至 RabbitMQ Broker,其中包含路由键、交换器等信息,根据路由键(RoutingKey)发送消息到交换机(Exchange) 6,相应的交换器(Exchange)根据接收到的路由键(RoutingKey)查找相匹配的队列如果找到 ,则将从生产者发送过来的消息存入相应的队列中 7,如果没有找到 ,则根据生产者配置的属性选择丢弃还是回退给生产者 8,关闭信道(Channel) 9,关闭链接(Connection)
消费者生产消息
1,建立链接(Connection) 2,在链接(Connection)上开启一个信道(Channel) 3,请求消费指定队列(Queue)的消息,并设置回调函数(onMessage) 4,[MQ]将消息推送给消费者,消费者接收消息 5,消费者发送消息确定(Ack[acknowledge]) 6,[MQ]删除被确认的消息 7,关闭信道(Channel) 8,关闭链接(Connection)
生产者(Producer):发送消息的应用。
消费者(Consumer):接收消息的应用。
队列(Queue):存储消息的缓存。
消息(Message):由生产者通过RabbitMQ发送给消费者的信息。
连接(Connection):连接RabbitMQ和应用服务器的TCP连接。
通道(Channel):连接里的一个虚拟通道。当你通过消息队列发送或者接收消息时,这个操作都是通过通道进行的。
交换机(Exchange):交换机负责从生产者那里接收消息,并根据交换类型分发到对应的消息列队里。要实现消息的接收,一个队列必须到绑定一个交换机。
绑定(Binding):绑定是队列和交换机的一个关联连接。
路由键(Routing Key):路由键是供交换机查看并根据键来决定如何分发消息到列队的一个键。路由键可以说是消息的目的地址。
三,消息到底是Broker推送给消费者的?还是消费者主动获取的?消费者消费消息有两种模式。
一种是Pull模式,对应的方法是basicGet。消息存放在服务端,只有消费者主动获取才能拿到消息。如果每搁一段时间获取一次消息,消息的实时性会降低。但是好处是可以根据自己的消费能力决定消息的频率。
另一种是push,对应的方法是BasicConsume,只要生产者发消息到服务器,就马上推送给消费者,消息保存客户端,实时性很高,如果消费不过来有可能会造成消息积压。Spring AMQP是push方式,通过事件机制对队列进行监听,只要有消息到达队列,就会触发消费消息的方法。
RabbitMQ中pull和push都有实现,kafka和RocketMQ只有pull。
四,交换机的Exchange路由方式
4.1 Direct 直连类型 (点对点)
routing key与binding key是一一对应的
一个队列与直连类型的交换机绑定,需指定一个明确的绑定建(binding key)。
生产者发送消息时恢携带一个路由键(routing key)
当消息的路由键与某个队列的绑定建完全匹配时,这条消息才会从交换机路由到这个队列上。多个队列也可以使用相同的绑定建。
直连类型的交换机,适用于一些业务用途明确的消息。
4.2 Topic 主题
一个routing key对应多个符合规则binding key
一个队列与主题烈性的交换机绑定时,可以在绑定键中使用通配符。支持两个通配符:
#代表0个或者多个单词
*代表不多不少一个单词
单词(Word)指的是用英文的"."隔开的字符,例如:a.bc.def是3个单词。
主题烈性的交换机适用于一些根据业务主题或者消息等级过滤消息的场景,比如说一条消息可能既跟资金有关,又跟风控有关,那就可以让这个消息制定一个多级的路由键。第一个单词代表跟资金相关,第二个单词代表跟风控相关,下游的业务系统的队列就可以使用不同的绑定键去接受消息了。
4.3 Fanout 广播
这种情况下不需要分析锁接受到的Routing key
广播类型的交换机与队列绑定时,不需要制定绑定键,因此生产者发送消息到广播类型交互机上,也不需要携带路由键。消息到达交换机时,所有与之绑定了的队列,都会受到相同的消息的副本。