前言本次分享RabbitMQ保护RabbitMQ过载的功能-FlowController(“流量控制”)。如果在使用RabbitMQ的时候不了解原理和场景,遇到FlowController很容易不知所措,今天我们就来了解一下它的原理。什么是流量控制?流量控制是一个在计算机网络和网络软件中存在了几十年的概念。本质上,它是一种向发送方施加背压以避免接收方过载的机制。接收器通常缓冲传入的数据包/消息,作为处理超过其处理速率的发送速率的一种方式。但是接收缓冲区不能永远增长,所以发送速率只能暂时超过接收方可以处理的(突发流量),或者发送方必须放慢速度(背压)。流量控制是一种将这种背压施加于发送方的方法,可以减慢它们的速度,这样接收方的缓冲区就不会溢出,延迟也不会变得太大。在发送方/接收方链中,这种背压可以向上传播到流量源。在更复杂的连接组件图中,流量控制可以平衡快速和慢速发送者之间的传入流量,避免过载,但允许系统以不同数量的发送者、不同速率和不同负载模式(稳定或突发)运行充分利用。RabbitMQ中的流量控制RabbitMQ看起来很像一个网络。每个RabbitMQBroker都是使用参与者模式在内部实现的,其中不同的组件通过消息传递相互通信,有时在本地,有时通过网络。还有发布者通过网络向代理发送消息,消费者从代理接收消息。消息流的简化描述将系统作为一个整体(代理和客户端)考虑,我们有四种可用的流量控制机制:基于信用的流量控制。内存报警。出版商确认。消费者确认和预取。基于信用的流量控制基于信用的流量控制是一种限制消息传入速率的方法。它允许系统内的各个参与者保护自己,并在他们不能足够快地处理消息时施加反压。它只针对那些有问题的连接、通道和队列,而不影响系统的其余部分。它的工作方式是系统中处理消息的每个参与者都使用“信用”作为对链施加反压的一种方式。如果通道要向队列发送消息,则需要信用。队列授予通道一些初始信用,然后通道发送到队列的每条消息都需要一个信用。当队列反过来能够将消息传递到持久层时,它会定期向通道授予更多信用。如果通道没有信用,它将被阻止向队列发送消息,直到队列授予它更多信用为止。这样通道就不能在队列上运行蛮力。经典队列的基于信用的流量控制所以我们有一个基于信用的流量控制链,它总是给发布者带来压力。最终,TCP背压将应用于发布者,因为TCP读取器进程在阻塞时不会从套接字读取。当连接、通道或队列用完信用时,它们将被阻塞,直到授予更多信用,这种状态称为“流动”。在管理UI中,您可能会看到处于流状态的连接、通道或队列,这表明该流最近发生过。这只是意味着他们暂时用完了信用,正在等待链中的下一个环节赶上来并给予一些信用。这可以每秒触发多次。CreditDrainingCreditGrants当队列或连接达到其吞吐量限制或下游瓶颈时,流状态可以在链中的不同点每秒触发多次,因为各个参与者的信用达到0然后得到补充。但这并不一定能阻止代理内存不足。传入消息并不总是内存使用率高的唯一主要原因,它也可能来自大队列和许多其他原因。内存警报如果基于信用的流量控制未能充分制动,或者如果内存使用由于其他原因增长到临界水平,内存警报将作为最后的手段启动,以防止代理崩溃(或被操作系统杀死)记忆。当内存警报开始时,所有发布者都被阻止。这就像您关闭了集群中传入消息的龙头。不是信用流控的目标限速,而是大锤。消费者可以继续消费,此时清空队列有望开始减少内存使用。在管理UI中,您会看到连接被阻止或在内存警报生效时被阻止。内存https://www.rabbitmq.com/memory.html。PublisheracknowledgementsPublisheracknowledgements的主要工作是数据安全,但它们在流量控制方面也起着重要作用。有三种使用发布者确认的方法:一次发送一个,在发送下一个之前等待每个确认(非常慢)。基于窗口。发送消息直到达到窗口大小(时间或消息数量),并在发送下一个窗口之前等待所有确认。流水线。允许发布者连续发送消息,但当未确认的消息计数(传输中的消息)达到限制时阻塞。随着确认的到来,可以发送更多消息,直到再次达到限制。流水线(或简称为异步)方法提供最高和最一致的吞吐量。它可以用作防止经纪人超载的额外保护,因为发布者自己甚至在向经纪人施加压力之前就将自己置于“流程”中。当您不使用发布者确认时,您仅依靠TCP流量控制来控制发布者和代理上已连接的读取器进程之间的链接。对于相对较少的发布者,TCP流量控制足以避免代理过载,但是当您有大量客户端时,TCP就不够用了,发布者确认对于集群在重负载下的稳定性是必要的。有趣的是,AMQP1.0添加了链路流量控制来克服这个问题。发布者确认https://www.rabbitmq.com/confirms.html。消费者确认和预取使用带有预取的手动确认会给RabbitMQ施加压力,以阻止它压倒您的消费者客户端。它使用流水线方法发送恒定的消息流,但将未确认消息的数量限制为预取(QoS)的大小。使用AutoAck模式,我们再次仅依赖TCP背压。客户端的各种入口缓冲区会很快填满。
