RabbitMQ面试题是Java面试经常问到的话题,今天给大家总结了一份RabbitMQ面试题及答案@mikechen
1、RabbitMQ是什么?
RabbitMQ是实现了高级消息队列协议(AMQP
)的开源消息代理软件,亦称面向消息的中间件。
RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端。
2、AMQP 是什么?
AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。
RabbitMQ 就是 AMQP 协议的 Erlang 的实现(当然 RabbitMQ 还支持 STOMP2、 MQTT3 等协议 )。
AMQP 协议的三层 :
Module Layer:协议最高层,主要定义了一些客户端调用的命令,客户端可以用这些命令实现自己的业务逻辑。
Session Layer:中间层,主要负责客户端命令发送给服务器,再将服务端应答返回客户端,提供可靠性同步机制和错误处理。
TransportLayer:最底层,主要传输二进制数据流,提供帧的处理、信道服用、错误检测和数据表示等。
AMQP模型主要包含三大组件
-
交换器 (Exchange):消息代理服务器中用于把消息路由到队列的组件。 -
队列 (Queue):用来存储消息的数据结构,位于硬盘或内存中。 -
绑定 (Binding):一套规则,告知交换器消息应该将消息投递给哪个队列。
3、为什么要使用RabbitMQ?
1.解耦
系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦。
2.异步
将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度。
3.削峰
并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常。
4、RabbitMQ有哪些特点?
1.可靠性:
RabbitMQ使用一些机制来保证可靠性, 如持久化、传输确认及发布确认等。
2.灵活的路由 :
在消息进入队列之前,通过交换器来路由消息。对于典型的路由功能, RabbitMQ 己经提供了一些内置的交换器来实现。针对更复杂的路由功能,可以将多个 交换器绑定在一起, 也可以通过插件机制来实现自己的交换器。
3.扩展性:
多个RabbitMQ节点可以组成一个集群,也可以根据实际业务情况动态地扩展 集群中节点。
4.高可用性
队列可以在集群中的机器上设置镜像,使得在部分节点出现问题的情况下队 列仍然可用。
5.多种协议:
RabbitMQ除了原生支持AMQP协议,还支持STOMP, MQTT等多种消息 中间件协议。
6.多语言客户端
RabbitMQ 几乎支持所有常用语言,比如 Java、 Python、 Ruby、 PHP、 C#、 JavaScript 等。
5、RabbitMQ 的缺点
1.系统可用性降低
系统引入的外部依赖越多,越容易挂掉,本来你就是A系统调用BCD三个系统的接口就好了,本来ABCD四个系统好好的,没啥问题,你偏加个MQ进来,万一MQ挂了咋整?MQ挂了,整套系统崩溃了,你不就完了么。
2.系统复杂性提高
硬生生加个MQ进来,你怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?
3.一致性问题
A系统处理完了直接返回成功了,本来都以为你这个请求就成功了;但是问题是,BD两个系统写库成功了,结果C系统写库失败了,咋整?你这数据就不一致了。
6、RabbitMQ的技术架构?
RabbitMQ的技术架构如下图所示:
1.生产者(Publisher)
发消息到RabbitMQ中的(Exchange)交换机上。
2.交换机(Exchange)
和生产者建立连接并接收生产者发来的消息
3.消费者(Consumer)
监听RabbitMQ中的(Queue)队列中的消息
4.队列(Queue)
Exchange将消息发送到指定的Queue中,Queue和消费者进行交互
5.路由(Routes)
交换机转发消息到队列的规则
7、RabbitMQ有那些基本概念?
- Broker:简单来说就是消息队列服务器实体;
- Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列;
- Queue:消息队列载体,每个消息都会被投入到一个或多个队列;
- Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来;
- Routing Key:路由关键字,exchange根据这个关键字进行消息投递;
- VHost:vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中);
- Producer:消息生产者,就是投递消息的程序;
- Consumer:消息消费者,就是接受消息的程序;
- Channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。
8、谈谈Broker服务节点、Queue队列、Exchange交换器?
1.Broker
Broker可以看做RabbitMQ的服务节点,一般请下一个Broker可以看做一个RabbitMQ服务器。
2.Queue
Queue是RabbitMQ的内部对象,用于存储消息,多个消费者可以订阅同一队列,这时队列中的消息会被平摊(轮询)给多个消费者进行处理。
3.Exchange
生产者将消息发送到交换器(Exchange),由交换器将消息路由到一个或者多个队列中,当路由不到时,或返回给生产者或直接丢弃。
9、RabbitMQ 有哪些工作模式?
RabbitMQ提供了6种模式:
1、简单模式
生产者,一个队列一个或多个消费者,当多个消费者同时监听一个队列时,他们并不能同时消费一条消息,而是随机消费消息,即一个队列中一条消息,只能被一个消费者消费。
2、主题模式(topic)
生产者,一个交换机(topicExchange),模糊匹配路由规则,多个队列,多个消费者。
3、订阅与发布模式(fanout)
生产者,一个交换机(fanoutExchange),没有路由规则,多个队列,多个消费者。生产者将消息不是直接发送到队列,而是发送到X交换机,然后由交换机发送给两个队列,两个消费者各自监听一个队列,来消费消息。
4、路由模式(direct)
生产者,一个交换机(directExchange),路由规则,多个队列,多个消费者。主要根据定义的路由规则决定消息往哪个队列发送。
5、RPC模式
对于RPC请求,客户端发送一条带有两个属性的消息:replyTo,设置为仅为请求创建的匿名独占队列,和correlationId,设置为每个请求的唯一id值。请求被发送到rpc_queue队列。RPC工作进程在队列上等待请求。当一个请求出现时,它执行任务,并使用replyTo字段中的队列将结果发回客户机。客户机在回应消息队列上等待数据。当消息出现时,它检查correlationId属性。如果匹配请求中的值,则向程序返回该响应数据。
6、工作队列
注释:默认情况下,RabbitMQ将按顺序将每条消息发送给下一个消费者,平均而言,每个消费者将获得相同数量的消息,这种分发消息的方式称为循环法。
10、RabbitMQ 如何保证消息的可靠性?
这里的可靠性分为三种:
- 消息到 MQ 的过程中搞丢
- MQ 自己搞丢
- MQ 到消费过程中搞丢
所以针对这三类的情况,如何保证可靠性呢?
生产者到 RabbitMQ,采用事务机制和 Confirm 机制,注意:事务机制和 Confirm 机制是互斥的,两者不能共存,会导致 RabbitMQ 报错。
RabbitMQ 自身,采用比如:持久化、集群、普通模式、镜像模式。
RabbitMQ 到消费者,采用比如:basicAck 机制、死信队列、消息补偿机制
11、RabbitMQ 消费者接收消息过程?
1.Producer先连接到Broker,建立连接Connection,开启一个信道(Channel)。
2.向Broker请求消费响应的队列中消息,可能会设置响应的回调函数。
3.等待Broker回应并投递相应队列中的消息,接收消息。
4.消费者确认收到的消息,ack。
5.RabbitMq从队列中删除已经确定的消息。
6.关闭信道。
7.关闭连接。
12、什么是延迟队列?RabbitMQ 怎么实现延迟队列?
延迟队列指的是存储对应的延迟消息,消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。
RabbitMQ本身是没有延迟队列的,要实现延迟消息,一般有两种方式:
通过RabbitMQ本身队列的特性来实现,需要使用RabbitMQ的死信交换机(Exchange)和消息的存活时间TTL(Time To Live)。
在RabbitMQ 3.5.7及以上的版本提供了一个插件(rabbitmq-delayed-message-exchange)来实现延迟队列功能。同时,插件依赖Erlang/OPT 18.0及以上。
也就是说,AMQP 协议以及RabbitMQ本身没有直接支持延迟队列的功能,但是可以通过TTL和DLX模拟出延迟队列的功能。
13、RabbitMQ中消息可能有的几种状态?
- alpha: 消息内容(包括消息体、属性和 headers) 和消息索引都存储在内存中 ;
- beta: 消息内容保存在磁盘中,消息索引保存在内存中;
- gamma: 消息内容保存在磁盘中,消息索引在磁盘和内存中都有 ;
- delta: 消息内容和索引都在磁盘中 。
14、如何保证 RabbitMQ 消息的顺序性?
拆分多个 queue(消息队列),每个 queue(消息队列) 一个 consumer(消费者),就是多一些 queue (消息队列)而已,确实是麻烦点;
或者就一个 queue (消息队列)但是对应一个 consumer(消费者),然后这个 consumer(消费者)内部用内存队列做排队,然后分发给底层不同的 worker 来处理。
15、如何保证RabbitMQ消息队列的高可用?
RabbitMQ 有三种模式:
1.单机模式
单机模式:就是demo级别的,一般就是你本地启动了玩玩儿的,没人生产用单机模式
2.普通集群模式
普通集群模式:意思就是在多台机器上启动多个RabbitMQ实例,每个机器启动一个。
3.镜像集群模式
镜像集群模式:这种模式才是所谓的RabbitMQ的高可用模式,跟普通集群模式不一样的是,你创建的queue,无论元数据(元数据指RabbitMQ的配置数据)还是queue里的消息都会存在于多个实例上,然后每次你写消息到queue的时候,都会自动把消息到多个实例的queue里进行消息同步。
作者简介
陈睿|mikechen(个人微信:mikechen68),10年+大厂架构经验,曾就职于阿里巴巴、淘宝、百度等一线互联网大厂。
以上!
关注作者「mikechen」公众号,获取更多架构面试干货!

后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》,后台回复【面试】即可获取《史上最全阿里Java面试题总结》