Rabbit MQ面试题

1、Rabbit MQ 的使用场景有哪些?

A.跨系统的异步通信。

所有需要异步交互的地方都可以使用消息队列。就像我们除了打电话(同步)以外,还需要发短信,发电子邮件(异步)的通讯方式。

B.多个应用之间的耦合。

由于消息是平台无关和语言无关的,而且语义上也不再是函数调用,因此更适合作为多个应用之间的松耦合的接口。基于消息队列的耦合,不需要发送方和接收方同时在线。在企业应用集成(EAI)中,文件传输,共享数据库,消息队列,远程过程调用都可以作为集成的方法。

C.应用内的同步变异步。

比如订单处理,就可以由前端应用将订单信息放到队列,后端应用从队列里依次获得消息处理,高峰时的大量订单可以积压在队列里慢慢处理掉。由于同步通常意味着阻塞,而大量线程的阻塞会降低计算机的性能。

D.消息驱动的架构(EDA)。

系统分解为消息队列,和消息制造者和消息消费者,一个处理流程可以根据需要拆成多个阶段(Stage),阶段之间用队列连接起来,前一个阶段处理的结果放入队列,后一个阶段从队列中获取消息继续处理。

E.应用需要更灵活的耦合方式,如发布订阅,比如可以指定路由规则。

F.跨局域网,甚至跨城市的通讯(CDN行业),比如北京机房与广州机房的应用程序的通信。

2Rabbit MQ有哪些重要的角色?

Rabbit MQ中重要的角色有:生产者、消费者和代理。

生产者:消息的创建者,负责创建和推送数据到消息服务器;

消费者:消息的接收方,用于处理数据和确认消息;

代理:就是Rabbit MQ本身,用于扮演“快递”的角色,本身不生产消息,只是扮演“快递”的角色。

3Rabbit MQ有哪些重要的组件?

Connection Factory(连接管理器):应用程序与Rabbit之间建立连接的管理器,程序代码中使用。

Channel(信道):消息推送使用的通道。

Exchange(交换器):用于接受、分配消息。

Queue(队列):用于存储生产者的消息。

Routing Key(路由键):用于把生成者的数据分配到交换器上。

Binding Key(绑定键):用于把交换器的消息绑定到队列上。

4Rabbit MQ的消息是怎么发送的?

首先客户端必须连接到Rabbit MQ服务器才能发布和消费消息,客户端和rabbit server之间会创建一个TCP连接,一旦TCP打开并通过了认证(认证就是你发送给 rabbit服务器的用户名和密码),你的客户端和Rabbit MQ就创建了一条AMQP信道(channel),信道是创建在“真实”TCP上的虚拟连接,AMQP命令都是通过信道发送出去的,每个信道都会有一个唯一的id,不论是发布消息,订阅队列都是通过这个信道完成的。

6Rabbit MQ怎么保证消息的稳定性?

提供了事务的功能。

通过将channel设置为confirm(确认)模式。

7Rabbit MQ怎么避免消息丢失?

消息持久化

ACK确认机制

设置集群镜像模式

消息补偿机制

8、要保证消息持久化成功的条件有哪些?

声明队列必须设置持久化durable设置为true.

消息推送投递模式必须设置持久化,delivery Mode设置为2(持久)。

消息已经到达持久化交换器。

消息已经到达持久化队列。

以上四个条件都满足才能保证消息持久化成功。

9、Rabbit MQ持久化有什么缺点?

持久化的缺就是降低了服务器的吞吐量,因为使用的是磁盘而非内存存储,从而降低了吞吐量。可尽量使用SSD硬盘来缓解吞吐量的问题。

10Rabbit MQ有几种广播类型?

三种广播模式:

Fan out: 所有bind到此exchange的queue都可以接收消息(纯广播,绑定到Rabbit MQ的接受者都能收到消息);

direct: 通过routing Key和exchange决定的那个唯一的queue可以接收消息;

topic:所有符合routing Key(此时可以是一个表达式)的routing Key所bind的queue可以接收消息;

11Rabbit MQ怎么实现延迟消息队列?

通过消息过期后进入死信交换器,再由交换器转发到延迟消费队列,实现延迟功能;

使用RabbitMQ-delayed-message-exchange插件实现延迟功能。

12Rabbit MQ集群有什么用?

集群主要有以下两个用途:

高可用:某个服务器出现问题,整个 Rabbit MQ 还可以继续使用;

高容量:集群可以承载更多的消息量。

13Rabbit MQ节点的类型有哪些?

磁盘节点:消息会存储到磁盘。

内存节点:消息都存储在内存中,重启服务器消息丢失,性能高于磁盘类型。

14. Rabbit MQ 集群搭建需要注意哪些问题?

各节点之间使用“--link”连接,此属性不能忽略。

各节点使用的erlang cookie值必须相同,此值相当于“秘钥”的功能,用于各节点的认证。

整个集群中必须包含一个磁盘节点。

15. Rabbit MQ每个节点是其他节点的完整拷贝吗?为什么?

不是,原因有以下两个:

存储空间的考虑:如果每个节点都拥有所有队列的完全拷贝,这样新增节点不但没有新增存储空间,反而增加了更多的冗余数据;

性能的考虑:如果每条消息都需要完整拷贝到每一个集群节点,那新增节点并没有提升处理消息的能力,最多是保持和单节点相同的性能甚至是更糟。

16. Rabbit MQ集群中唯一一个磁盘节点崩溃了会发生什么情况?

如果唯一磁盘的磁盘节点崩溃了,不能进行以下操作:

不能创建队列

不能创建交换器

不能创建绑定

不能添加用户

不能更改权限

不能添加和删除集群节点

唯一磁盘节点崩溃了,集群是可以保持运行的,但你不能更改任何东西。

17. Rabbit MQ对集群节点停止顺序有要求吗?

Rabbit MQ 对集群的停止的顺序是有要求的,应该先关闭内存节点,最后再关闭磁盘节点。如果顺序恰好相反的话,可能会造成消息的丢失。

18RabbitMQ 中的 Broker 是指什么?Cluster 又是指什么?

答:broker 是指一个或多个erlang node的逻辑分组,且node上运行着RabbitMQ 应用程序。cluster 是在broker的基础之上,增加了 node 之间共享元数据的约束。

19什么是元数据?元数据分为哪些类型?包括哪些内容?与 cluster 相关的元数据有哪些?元数据是如何保存的?元数据在 cluster 中是如何分布的?

答:在非 cluster 模式下,元数据主要分为 Queue 元数据(queue 名字和属性等)、Exchange 元数据(exchange 名字、类型和属性等)、Binding 元数据(存放路由关系的查找表)、Vhost 元数据(vhost 范围内针对前三者的名字空间约束和安全属性设置)。在cluster 模式下,还包括 cluster 中 node 位置信息和 node 关系信息。元数据按照 erlang node 的类型确定是仅保存于 RAM 中,还是同时保存在 RAM 和 disk 上。元数据在cluster 中是全 node 分布的。

下图所示为 queue 的元数据在单 node 和 cluster 两种模式下的分布图。

20RAM node 和 disk node 的区别?

RAM node 仅将 fabric(即 queue、exchange 和 binding 等 RabbitMQ 基础构件)相关元数据保存到内存中,但 disk node 会在内存和磁盘中均进行存储。RAM node 上唯一会存储到磁盘上的元数据是 Cluster 中使用的 disk node 的地址。要求在 RabbitMQ cluster中至少存在一个 disk node 。

21、RabbitMQ 上的一个 queue 中存放的 message 是否有数量限制?

答:可以认为是无限制,因为限制取决于机器的内存,但是消息过多会导致处理效率的下降。

22RabbitMQ 概念里的 Channel、Exchange 和 Queue 这些东东是逻辑概念,还是对应着进程实体?这些东东分别起什么作用?

Queue 具有自己的erlang 进程;Exchange 内部实现为保存 binding 关系的查找表;

Channel 是实际进行路由工作的实体,即负责按照 routing_key 将 message 投递给queue 。由 AMQP 协议描述可知,channel 是真实 TCP 连接之上的虚拟连接,所有AMQP 命令都是通过 channel 发送的,且每一个 channel 有唯一的 ID。一个 channel 只能被单独一个操作系统线程使用,故投递到特定 channel 上的 message 是有顺序的。但一个操作系统线程上允许使用多个 channel 。channel 号为 0 的 channel 用于处理所有对于当前 connection 全局有效的帧,而 1-65535 号 channel 用于处理和特定 channel 相关的帧。AMQP 协议给出的 channel 复用模型如下其中每一个 channel 运行在一个独立的线程上,多线程共享同一个 socket。

23、vhost 是什么?起什么作用?

答:vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。

24、在单node系统和多node 构成的cluster 系统中声明 queue、exchange ,以及进行 binding 会有什么不同?

答:当你在单 node 上声明 queue 时,只要该node上相关元数据进行了变更,你就会得到 Queue.Declare-ok回应;而在cluster上声明queue ,则要求 cluster 上的全部node都要进行元数据成功更新,才会得到 Queue.Declare-ok 回应。另外,若 node 类型为 RAM node则变更的数据仅保存在内存中,若类型为 disk node 则还要变更保存在磁盘上的数据。

25客户端连接到cluster中的任意node上是否都能正常工作?

答:是的。客户端感觉不到有何不同。

26若 cluster中拥有某个 queue 的 owner node 失效了,且该 queue 被声明具有durable 属性,是否能够成功从其他 node 上重新声明该 queue ?

答:不能,在这种情况下,将得到 404 NOT_FOUND 错误。只能等 queue 所属的 node恢复后才能使用该 queue 。但若该 queue 本身不具有 durable 属性,则可在其他 node上重新声明。

27cluster中node的失效会对 consumer 产生什么影响?若是在 cluster 中创建了mirrored queue ,这时 node 失效会对 consumer 产生什么影响?

答:若是 consumer 所连接的那个 node 失效(无论该 node 是否为 consumer 所订阅queue 的 owner node),则 consumer 会在发现 TCP 连接断开时,按标准行为执行重连逻辑,并根据“Assume Nothing”原则重建相应的 fabric 即可。若是失效的 node 为consumer 订阅 queue 的 owner node,则 consumer 只能通过 Consumer Cancellation Notification 机制来检测与该 queue 订阅关系的终止,否则会出现傻等却没有任何消息来到的问题。

28能够在地理上分开的不同数据中心使用 RabbitMQ cluster么?

答:不能。第一,你无法控制所创建的 queue 实际分布在 cluster 里的哪个 node 上(一般使用 HAProxy + cluster 模型时都是这样),这可能会导致各种跨地域访问时的常见问题;第二,Erlang 的 OTP 通信框架对延迟的容忍度有限,这可能会触发各种超时,导致业务疲于处理;第三,在广域网上的连接失效问题将导致经典的“脑裂”问题,而RabbitMQ 目前无法处理(该问题主要是说 Mnesia)。

29为什么 heavy RPC 的使用场景下不建议采用disk node ?

答:heavy RPC 是指在业务逻辑中高频调用 RabbitMQ 提供的 RPC 机制,导致不断创建、销毁 reply queue ,进而造成 disk node 的性能问题(因为会针对元数据不断写盘)。所以在使用 RPC 机制时需要考虑自身的业务场景。

30向不存在的 exchange 发publish消息会发生什么?向不存在的queue执行consume动作会发生什么?

答:都会收到 Channel.Close 信令告之不存在(内含原因 404 NOT_FOUND)。

31routing_key和binding_key 的最大长度是多少?

答:255 字节。

32RabbitMQ允许发送的 message 最大可达多大?

答:根据 AMQP 协议规定,消息体的大小由 64-bit 的值来指定,所以你就可以知道到底能发多大的数据了。

33什么情况下 producer 不主动创建 queue 是安全的?

答:1.message 是允许丢失的;2.实现了针对未处理消息的 republish 功能(例如采用Publisher Confirm 机制)。

34“dead letter”queue 的用途?

答:当消息被RabbitMQ server投递到 consumer后,但 consumer 却通过 Basic.Reject进行了拒绝时(同时设置 requeue=false),那么该消息会被放入“dead letter”queue 中。该 queue可用于排查 message 被 reject 或 undeliver的原因。

35为什么说保证 message 被可靠持久化的条件是 queue 和 exchange 具有durable 属性,同时 message 具有 persistent 属性才行?

答:binding 关系可以表示为 exchange – binding – queue 。从文档中我们知道,若要求投递的 message 能够不丢失,要求 message 本身设置 persistent 属性,要求 exchange和 queue 都设置 durable 属性。其实这问题可以这么想,若 exchange 或 queue 未设置durable 属性,则在其 crash 之后就会无法恢复,那么即使 message 设置了 persistent 属性,仍然存在 message 虽然能恢复但却无处容身的问题;同理,若 message 本身未设置 persistent 属性,则 message 的持久化更无从谈起。

36、什么情况下会出现blackholed问题?

答:blackholed 问题是指,向exchange投递了message,而由于各种原因导致该message 丢失,但发送者却不知道。可导致blackholed 的情况:

1.向未绑定queue的exchange 发送 message;

2.exchange 以binding_key key_A绑定了queue queue_A,但向该 exchange 发送 message 使用的 routing_key 却是 key_B。

37、如何防止出现 blackholed问题?

没有特别好的办法,只能在具体实践中通过各种方式保证相关 fabric 的存在。另外,如果在执行 Basic.Publish 时设置 mandatory=true ,则在遇到可能出现 blackholed 情况时,服务器会通过返回 Basic.Return 告之当前 message 无法被正确投递(内含原因 312NO_ROUTE)。

38、Consumer Cancellation Notification 机制用于什么场景?

答:用于保证当镜像 queue 中 master 挂掉时,连接到 slave 上的 consumer 可以收到自身 consume 被取消的通知,进而可以重新执行 consume 动作从新选出的 master 出获得消息。若不采用该机制,连接到 slave 上的 consumer 将不会感知 master 挂掉这个事情,导致后续无法再收到新 master 广播出来的 message 。另外,因为在镜像 queue 模式下,存在将 message 进行 requeue 的可能,所以实现 consumer 的逻辑时需要能够正确处理出现重复 message 的情况。

39、Basic.Reject 的用法是什么?

该信令可用于consumer对收到的message进行reject。若在该信令中设置requeue=true,则当 RabbitMQ server 收到该拒绝信令后,会将该 message 重新发送到下一个处于 consume 状态的 consumer 处(理论上仍可能将该消息发送给当前consumer)。若设置 requeue=false ,则 RabbitMQ server在收到拒绝信令后,将直接将该message从queue 中移除。

另外一种移除queue中message 的小技巧是,consumer回复Basic.Ack但不对获取到的message 做任何处理。

而Basic.Nack 是对 Basic.Reject的扩展,以支持一次拒绝多条message的能力。

40、为什么不应该对所有的 Message 都使用持久化机制?

首先,必然导致性能的下降,因为写磁盘比写RAM慢的多,message的吞吐量可能有10倍的差距。

其次,message 的持久化机制用在Rabbit MQ 的内置cluster方案时会出现“坑爹”问题。矛盾点在于,若message设置了persistent 属性,但queue未设置durable 属性,那么当该 queue 的 owner node 出现异常后,在未重建该 queue 前,发往该 queue 的 message 将被 blackholed;

若 message 设置了 persistent 属性,同时queue 也设置了 durable 属性,那么当 queue 的 owner node 异常且无法重启的情况下,则该 queue 无法在其他 node 上重建,只能等待其 owner node 重启后,才能恢复该 queue 的使用,而在这段时间内发送给该 queue 的 message 将被 blackholed。

所以,是否要对 message 进行持久化,需要综合考虑性能需要,以及可能遇到的问题。若想达到 100,000 条/秒以上的消息吞吐量(单 Rabbit MQ 服务器),则要么使用其他的方式来确保 message 的可靠 delivery,要么使用非常快速的存储系统以支持全持久化(例如使用 SSD)。另外一种处理原则是:仅对关键消息作持久化处理(根据业务重要程度),且应该保证关键消息的量不会导致性能瓶颈。

41Rabbit MQ中的cluster、mirrored queue,以及 warrens机制分别用于解决什么问题?存在哪些问题?

Cluster:为了解决当cluster中的任意node失效后,producer和 consumer均可以通过其他node继续工作,即提高了可用性;另外可以通过增加node数量增加cluster的消息吞吐量的目的。

cluster本身不负责message的可靠性问题(该问题由producer通过各种机制自行解决);cluster无法解决跨数据中心的问题(即脑裂问题)。另外,在cluster前使用HAProxy可以解决node的选择问题,即业务无需知道cluster中多个node的IP地址。可以利用HAProxy 进行失效node的探测,可以作负载均衡。下图为HAProxy + cluster 的模型。

Mirrored queue:为了解决使用cluster时所创建的queue的完整信息仅存在于单一node上的问题,从另一个角度增加可用性。若想正确使用该功能,需要保证:

1.consumer需要支持 Consumer Cancellation Notification机制;

2.consumer必须能够正确处理重复message。

Warrens:是为了解决cluster中message可能被blackholed的问题,即不能接受producer 不停republish message但RabbitMQ server无回应的情况。Warrens 有两种构成方式,一种模型是两台独立的 RabbitMQ server + HAProxy ,其中两个 server 的状态分别为 active和hot-standby。该模型的特点为:两台server之间无任何数据共享和协议交互,两台server可以基于不同的 Rabbit MQ 版本。如下图所示

另一种模型为两台共享存储的 RabbitMQ server + keepalived ,其中两个 server 的状态分别为 active 和 cold-standby 。该模型的特点为:两台 server 基于共享存储可以做到完全恢复,要求必须基于完全相同的 RabbitMQ 版本。如下图所示

Warrens模型存在的问题:对于第一种模型,虽然理论上讲不会丢失消息,但若在该模型

上使用持久化机制,就会出现这样一种情况,即若作为 active 的 server 异常后,持久化

在该 server 上的消息将暂时无法被 consume ,因为此时该 queue 将无法在作为 hotstandby 的 server 上被重建,所以,只能等到异常的 active server 恢复后,才能从其上的queue 中获取相应的 message 进行处理。而对于业务来说,需要具有:a.感知 AMQP 连接断开后重建各种 fabric 的能力;b.感知 active server 恢复的能力;c.切换回 active server 的时机控制,以及切回后,针对 message 先后顺序产生的变化进行处理的能力。

对于第二种模型,因为是基于共享存储的模式,所以导致 active server 异常的条件,可能同样会导致 cold-standby server 异常;另外,在该模型下,要求 active 和 cold-standby的 server 必须具有相同的 node 名和 UID ,否则将产生访问权限问题;最后,由于该模型是冷备方案,故无法保证 cold-standby server 能在你要求的时限内成功启动。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值