rabbitmq學習與分享(4)

zxhy發表於2019-04-15

一.前言

在上一篇文章中介紹了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佔用的記憶體超過這個閾值時,就會阻塞所有生產者的連線。

磁碟預警

rabbitmq 針對磁碟這塊也設定了相應的預警引數:disk_free_limit也支援了幾種引數形式的配置:

  {disk_free_limit, 50000000},
  {disk_free_limit, "50MB"},
  {disk_free_limit, {mem_relative, 2.0}}
複製程式碼

rabbitmq當記憶體吃緊時,一些非持久化的訊息也會通過換頁到磁碟。具體什麼時候開始進行換頁,可以通過引數{vm_memory_high_watermark_paging_ratio, 0.5} 進行設定.

一旦broker佔用的磁碟記憶體超過閾值時,也會阻塞所有的生產者連線。

流控

流控機制用來避免訊息的傳送速率過快導致難以支撐的情形,磁碟預警和記憶體預警相當於全域性的流控,一旦達到這個預警值時就會阻塞所有的生產者連線。

針對單連線的流控:

rabbitmq流控機制原理實質上就是通過監控各erlang程式的mailbox,當某個程式負載過高來不及接收訊息時,這個程式的mailbox就會開始堆積訊息,當堆積到一定量時,就會阻塞住上游程式讓其不得接收新訊息,從而慢慢上游程式的mailbox也會開始積壓訊息,到了一定的量也會阻塞上游的上游的程式接收訊息,最後就會使得負責網路資料包接收的程式阻塞掉,暫停接收資料。這就有點像一個多級的水庫,當下游水庫壓力過大時,上游水庫就得關閉閘門,使得自己的壓力也越來越大這就需要關閉更上游的水庫閘門直到關閉最最上游的閘門。

rabbitmq 採用credit 演算法來實現這個過程的:

rabbitmq學習與分享(4)

credit_from :表示能向下遊傳送多少訊息,每傳送一條,相應的value減一。 credit_to :表示能再接收多少訊息,就向上遊傳送增加credit_from xx值.

當上遊的傳送頻率高於下游的接收速率時,credit_from 的值就會逐漸被耗光,這時上游的傳送程式就會阻塞,當上遊收到下游傳送的增加credit_from 值的通知時,上游就會解除阻塞,能繼續傳送訊息。 這樣就會將傳送訊息的速率限制在一個區間內,達到實現流控的目的。

總結

本文主要介紹了rabbitmq 流控實現的相關手段,參考資料以及相關的文件.

流控機制不僅作用於connection ,也作用於channel,queue等等元件,具體的細節可以參考相應的文件和書籍資料進行進一步深入學習。

相關文章