在上一篇文章中介紹了rabbitmq經過集羣以及鏡像隊列的相關機制避免了broker的單點故障。可是有沒有想過一個問題,若是消息的生產者比較多,或者發送消息的頻率很快,或者消費者消費消息的速度很慢,是否是就會致使消息積壓,可是內存或者磁盤空間是有限的啊,消息不斷的積壓,最後不會致使內存或者磁盤被撐爆麼?本篇文章主要是針對這個問題,看看rabbitmq是如何處理的作一個學習分享。算法
整體而言,rabbitmq 提供瞭如下幾種機制來避免這種狀況的發生:網絡
rabbitmq 提供了內存預警的相關配置,也能夠經過rabbitmqctl 客戶端命令進行動態設置:,涉及到的相關參數以下:vm_memory_high_watermark(能夠採用多種參數形式設置)學習
{vm_memory_high_watermark, 0.4}
{vm_memory_high_watermark, {absolute, 1073741824}}
{vm_memory_high_watermark, {absolute, "1024M"}},
複製代碼
一旦broker佔用的內存超過這個閾值時,就會阻塞全部生產者的鏈接。spa
rabbitmq 針對磁盤這塊也設置了相應的預警參數:disk_free_limit也支持了幾種參數形式的配置:code
{disk_free_limit, 50000000},
{disk_free_limit, "50MB"},
{disk_free_limit, {mem_relative, 2.0}}
複製代碼
rabbitmq當內存吃緊時,一些非持久化的消息也會經過換頁到磁盤。具體何時開始進行換頁,能夠經過參數{vm_memory_high_watermark_paging_ratio, 0.5} 進行設置.cdn
一旦broker佔用的磁盤內存超過閾值時,也會阻塞全部的生產者鏈接。blog
流控機制用來避免消息的發送速率過快致使難以支撐的情形,磁盤預警和內存預警至關於全局的流控,一旦達到這個預警值時就會阻塞全部的生產者鏈接。rabbitmq
針對單鏈接的流控:隊列
rabbitmq流控機制原理實質上就是經過監控各erlang進程的mailbox,當某個進程負載太高來不及接收消息時,這個進程的mailbox就會開始堆積消息,當堆積到必定量時,就會阻塞住上游進程讓其不得接收新消息,從而慢慢上游進程的mailbox也會開始積壓消息,到了必定的量也會阻塞上游的上游的進程接收消息,最後就會使得負責網絡數據包接收的進程阻塞掉,暫停接收數據。這就有點像一個多級的水庫,當下游水庫壓力過大時,上游水庫就得關閉閘門,使得本身的壓力也愈來愈大這就須要關閉更上游的水庫閘門直到關閉最最上游的閘門。進程
rabbitmq 採用credit 算法來實現這個過程的:
credit_from :表示能向下遊發送多少消息,每發送一條,相應的value減一。 credit_to :表示能再接收多少消息,就向上遊發送增長credit_from xx值.
當上遊的發送頻率高於下游的接收速率時,credit_from 的值就會逐漸被耗光,這時上游的發送進程就會阻塞,當上遊收到下游發送的增長credit_from 值的通知時,上游就會解除阻塞,能繼續發送消息。 這樣就會將發送消息的速率限制在一個區間內,達到實現流控的目的。
本文主要介紹了rabbitmq 流控實現的相關手段,參考資料以及相關的文檔.
流控機制不只做用於connection ,也做用於channel,queue等等組件,具體的細節能夠參考相應的文檔和書籍資料進行進一步深刻學習。