RabbitMQ学习笔记(1)----消息队列

821 阅读4分钟

参考网址:

1. https://www.jianshu.com/p/689ce4205021
2. https://zhuanlan.zhihu.com/p/52773169
3. https://juejin.cn/post/6844903817348136968#heading-2

1. 什么是消息队列

套话

消息队列是分布式系统中重要组件,主要用于处理应用解耦、异步消息、流量削峰等问题,实现高性能、高可用、可伸缩和最终一致性架构。

个人理解

消息队列是一种存放消息的容器,具备以下特点:

  • (1)先进先出。消息的消费顺序与消息被生产的顺序一致。
  • (2)异步处理。消息的生产和消费之间是异步的,生产者将消息放入消息队列之后不需要关系消息被谁消费,如何被消费。生产者和消费者之间彼此不关心对方是谁。

2. 为什么使用消息队列(消息队列应用场景)

消息队列常被用来(1)解耦,(2)异步处理,(3)流量削峰/限流,(4)日志处理,(5)消息通信。接下来分别介绍这几种消息队列的应用场景。

2.1 解耦(消息队列所解决最本质的问题)

假如B系统、C系统、D系统都需要A系统的userId,或者还会有更多的系统需要,那么A系统需要将数据给每个系统都发送一份,甚至有可能B、C、D系统过段时间就修改用来接收A系统数据的接口,A系统也要作更改,这使得A系统难以维护。
(比如说A系统是一个用户登录模块,B系统是一个消息发送模块,C系统是一个用户状态维护模块,B、C系统都需要在用户登录处理些任务,并需要用户的userId,这时A通过将userId发送给其它系统来通知用户登录信息)

可以通过引入消息队列,A系统将userId写入消息队列,其它系统自己去消息队列去消费,A不关心谁需要userId。

2.2 异步处理(提高系统处理能力)

通过引入消息队列,将一些非核心逻辑,进行异步处理。

用户注册场景

场景说明:用户注册后,需要存储注册信息、发注册邮件和注册短信,其中发注册邮件和短信是一种非核心业务,并且可以在注册消息存储之后理解返回注册成功,异步执行发送邮件和短信的操作。
假设存储信息、发送邮件和短信均耗时50ms。

(1)串行方式:顺序执行完所有操作后返回。

(2)并行方式:存储注册信息后,并行执行发送邮件和短信的操作,两个任务都执行完毕后返回。

(3)引入消息队列,将注册信息写入消息队列后即返回,非核心任务消费消息队列后异步处理。

(4)比较

单次请求串行耗时150ms,并行耗时100ms,引入消息队列耗时55ms。引入消息队列后,每秒能够处理请求数比串行提升3倍,比并行提升2倍。

2.3 流量削峰/限流

消息队列还可以用于限流。先将所有请求写入到队列(相当于水库),处理请求时可以按照一定策略去消费消息,从而控制处理消息时的频率(控制出水速率)。 (个人理解,如果不是分布式系统的话,仅仅使用JDK层级的BlockingQueue就可以进行限流)

处理消息的策略有很多,比如计数器法和令牌桶算法等。

2.4 日志处理

消息队列还可以用于日志采集,来解决大量日志传输问题。常见方案:Log Agent(flume) -> Log server(kafka) -> ElasticSearch -> Kibana

2.5 消息通信

消息队列一般内置了高效的消息通信机制,也可以用于系统间纯消息通讯。
点对点通讯和聊天室通信通讯架构都可以实现,可以所有用户都向一个队列发送消息并订阅,也可以借助MQ的一些模式来实现,比如RabbitMq有exchange和routingKey。

项目实际问题

背景:A系统需要给B系统发送消息,但B系统分布式部署,存在多个节点,每个节点中有多台机器,每个节点对有各自的vip,节点内机器被负载均衡所调度。
需求:现在A系统需要给B系统中某个节点的具体机器发送消息,但是A系统只知道节点的vip,而无法直接将请求定位到具体的机器。
方案:引入消息队列,A系统在向B系统机器(节点N1,机器M1)发送消息时,将消息发送到消息队列的exchange(exchangeName=N1,routingKey=M1机器在N1节点中局域网Ip),M1机器监听队列,并绑定到对应exchange。这样解决了M1机器在负载均衡背后,A系统无法直接发消息给M1机器的问题。