1、RabbitMQ中的broker是指什么?cluster又是指什么?
broker是指一个或多个erlang node的逻辑分组,且node上运行着 RabbitMQ应用程序。cluster是在broker的基础之上,增加了 node之间 共享元数据的约束。
2、什么是元数据?元数据分为哪些类型?包括哪些内容?与cluster相关的元数据有哪些?元数据是如何保存的?元数据在cluster中是如何分布的?
在非cluster模式下,元数据主要分为Queue元数据(queue名字和属性 等)、Exchange元数据(exchange名字、类型和属性等)、Binding元数据 (存放路由关系的查找表)、Vhost元数据(vhost范围内针对前三者的名字空 间约束和安全属性设置)。
在cluster模式下,还包括cluster中node位置信息和node关系信息。元数据按照erlang node的类型确定是仅保存于RAM中,还是同时保存在RAM和disk上。元数据在cluster中是全node 分布的。
3、RAM node 和 disk node 的区别?
RAM node 仅将 fabric(即 queue、exchange 和 binding等 RabbitMQ基础构 件)相关元数据保存到内存中,但disk node会在内存和磁盘中均进行存 储。RAM node上唯一会存储到磁盘上的元数据是cluster中使用的disk node的地址。要求在RabbitMQ cluster中至少存在一个disk node。
4、RabbitMQ上的一个queue中存放的message是否有数量限制?
可以认为是无限制,因为限制取决于机器的内存,但是消息过多会导致处 理效率的下降。
5、vhost是什么?起什么作用?
vhost可以理解为虚拟broker ,即mini-RabbitMQ server。其内部均含有 独立的queue、exchange和binding等,但最最重要的是,其拥有独立的 权限系统,可以做到vhost范围的用户控制。当然,从RabbitMQ的全局 角度,vhost可以作为不同权限隔离的手段(一个典型的例子就是不同的应 用可以跑在不同的vhost中)。
6、在单node系统和多node构成的cluster系统中声明queue、exchange,以及进行binding会有什么不同?
当你在单node上声明queue时,只要该node上相关元数据进行了变 更,你就会得到Queue.Declare-ok回应;而在cluster上声明queue,则要 求cluster上的全部node都要进行元数据成功更新,才会得到 Queue.Declare-ok回应。另外,若node类型为RAM node则变更的数据 仅保存在内存中,若类型为disk node则还要变更保存在磁盘上的数据。
7、客户端连接到cluster中的任意node上是否都能正常工作?
是的。客户端感觉不到有何不同。
8、若cluster中拥有某个queue的owner node失效了,且该queue 被声明具有durable属性,是否能够成功从其他node上重新声明该 queue ?
不能,在这种情况下,将得到404 NOT_FOUND错误。只能等queue所 属的node恢复后才能使用该queue。但若该queue本身不具有durable 属性,则可在其他node上重新声明。
9、cluster中node的失效会对consumer产生什么影响?若是在 cluster 中创建了 mirrored queue,这时 node 失效会对 consumer 产生什么影响?
若是consumer所连接的那个node失效(无论该node是否为consumer 所订阅queue的owner node),则consumer会在发现TCP连接断开时, 按标准行为执行重连逻辑,并根据“Assume Nothing”原则重建相应的 fabric 即可。若是失效的 node 为 consumer 订阅 queue 的 o wner node, 则 consumer 只能通过 Consumer Cancellation Notification 机制来检测与 该queue订阅关系的终止,否则会出现傻等却没有任何消息来到的问 题。
10、能够在地理上分开的不同数据中心使用RabbitMQ cluster么?
不能。
第一,你无法控制所创建的queue实际分布在cluster里的哪个node上 (一般使用HAProxy + cluster模型时都是这样),这可能会导致各种跨地域 访问时的常见问题;
第二,Erlang的OTP通信框架对延迟的容忍度有限,这可能会触发各种 超时,导致业务疲于处理;
第三,在广域网上的连接失效问题将导致经典的“脑裂"问题,而 RabbitMQ目前无法处理(该问题主要是说Mnesia)。
11、为什么heavy RPC的使用场景下不建议采用disk node
heavy RPC是指在业务逻辑中高频调用RabbitMQ提供的RPC机制,导 致不断创建、销毁reply queue,进而造成disk node的性能问题(因为会 针对元数据不断写盘)。所以在使用RPC机制时需要考虑自身的业务场景。
12、向不存在的exchange发publish消息会发生什么?向不存在的 queue执行c onsume动作会发生什么?
都会收到ChanneLClose信令告之不存在(内含原因404 NOT_FOUND)。
13、routing_key和binding_key的最大长度是多少?
255字节。
14、RabbitMQ允许发送的message最大可达多大?
根据AMQP协议规定,消息体的大小由64-bit的值来指定,所以你就可 以知道到底能发多大的数据了。
15、什么情况下producer不主动创建queue是安全的?
message是允许丢失的;
实现了针对未处理消息的republish功能(例如采用Publisher Confirm机 制)。
16、"dead letter" queue 的用途?
当消息被RabbitMQ server投递到consumer后,但consumer却通过 Basic.Reject进行了拒绝时(同时设置requeue=false),那么该消息会被放 入“dead letter"queue 中。该 queue 可用于排查 message 被 reject 或 undeliver 的原因。
17、什么说保证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的持久化更无从谈起。
18、什么情况下会出现blackholed问题?
blackholed问题是指,向exchange投递了 message,而由于各种原因导 致该message丢失,但发送者却不知道。可导致blackholed的情况:
向未绑定 queue 的 exchange 发送 message;
exchange 以 binding_key key_A 绑定了 queue queue_A,但向该 exchange 发送 message 使用的 routing_key 去卩是 key_B。
19、如何防止出现blackholed问题?
没有特别好的办法,只能在具体实践中通过各种方式保证相关fabric的存 在。另外,如果在执行Basic.Publish时设置mandatory=true,则在遇到 可能出现blackholed情况时,服务器会通过返回Basic.Return告之当前 message无法被正确投递(内含原因312 NO_ROUTE)。
20、Consumer Cancellation Notification 机制用于什么场景?
用于保证当镜像queue中master挂掉时,连接到slave上的consumer可 以收到自身consume被取消的通知,进而可以重新执行consume动作从 新选出的master出获得消息。
若不采用该机制,连接到slave上的 consumer将不会感知master挂掉这个事情,导致后续无法再收到新 master广播出来的message。
另外,因为在镜像queue模式下,存在将 message进行requeue的可能,所以实现consumer的逻辑时需要能够正 确处理出现重复message的情况。
21、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 的能力。
22、为什么不应该对所有的message都使用持久化机制?
首先,必然导致性能的下降,因为写磁盘比写RAM慢的多,message的 吞吐量可能有10倍的差距。其次,message的持久化机制用在 RabbitMQ的内置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条/秒以上的消息吞吐量(单RabbitMQ服务器),则要么使用其他 的方式来确保message的可靠delivery,要么使用非常快速的存储系统以 支持全持久化(例如使用SSD)。另外一种处理原则是:仅对关键消息作持久 化处理(根据业务重要程度),且应该保证关键消息的量不会导致性能瓶 颈。
23、RabbitMQ 中的 cluster、mirrored queue,以及 warrens 机制分 别用于解决什么问题?存在哪些问题?
cluster是为了解决当cluster中的任意node失效后,producer和 consumer均可以通过其他node继续工作,即提高了可用性;另外可以通 过增加node数量增加cluster的消息吞吐量的目的。
cluster本身不负责 message的可靠性问题(该问题由producer通过各种机制自行解 决);cluster无法解决跨数据中心的问题(即脑裂问题)。
另外,在cluster前使用HAProxy可以解决node的选择问题,即业务无 需知道cluster中多个node的ip地址。可以利用HAProxy进行失效node 的探测,可以作负载均衡。
Mirrored queue是为了解决使用cluster时所创建的queue的完整信息仅 存在于单一node上的问题,从另一个角度增加可用性。若想正确使用该 功能,需要保证:
consumer 需要支持 Consumer Cancellation Notification 机制;
consumer必须能够正确处理重复message。
Warrens是为了解决cluster中message可能被blackholed的问题,即不 能接受 producer 不停 republish message 但 RabbitMQ server 无回应的情况。Warrens有两种构成方式:
一种模型是两台独立的RabbitMQ server + HAProxy,其中两个server的 状态分别为active和hot-standby。该模型的特点为:两台server之间无任 何数据共享和协议交互,两台server可以基于不同的RabbitMQ版本。
另一种模型为两台共享存储的RabbitMQ server + keepalived,其中两个 server 的状态分别为 active 和 cold-standby。
该模型的特点为:两台server基于共享存储可以做到完全恢复,要求必须 基于完全相同的RabbitMQ版本。
Warrens模型存在的问题:
对于第一种模型,虽然理论上讲不会丢失消息,但若在该模型上使用持久 化机制,就会出现这样一种情况,即若作为active的server异常后,持久 化在该server上的消息将暂时无法被consume,因为此时该queue将无 法在作为hot- standby的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能在你要求的时限内成功启动。