RabbitMQ 記憶體和磁碟警告
記憶體和磁碟警告
有兩種情況下,Rabbit MQ會停止讀取客戶端的連線socket,為了防止crash崩潰,這兩種情況是:
記憶體使用達到配置值
磁碟空間下降到配置值下
在這兩種情況下,伺服器會臨時阻塞連線—伺服器會暫停讀取釋出訊息的客戶端的連線,連線心跳監控也會被禁用,在rabbitmqctl和管理查建中的所有網路連線如果是blocking狀態,以為著他們沒有嘗試傳送,因此可以繼續,如果是blocked狀態,意味著他們已經發布了,現在需要被暫停。
叢集的警告
當執行Rabbit MQ叢集的時候,記憶體和磁碟警告是叢集範圍的,如果一個節點達到了限制,所有的節點都會阻塞連線。
這樣的意圖是停止生產者,但是讓消費者繼續不受影響,但是因為協議允許生產者和消費者在同一個Channel或者同一個連線的不同Channel上進行操作,這個邏輯是不完美的,在實踐中,不會產生任何問題,因為節流作為一種延遲被觀察,儘管如此,建議使用單獨的連線分別作為生產和消費。
檔案描述符耗盡 Running out of File Descriptors
當伺服器使用了作業系統分配給它的所有檔案描述符,它會拒絕客戶端連線,參考 “網路指南” 學習更多。
當客戶端嘗試傳送比伺服器接收訊息快的時候,它們會進入瞬時的流控。
相關主題
記憶體如何限制工作
磁碟如何限制工作
客戶端可以檢測它們是否被阻塞
記憶體警告
Rabbit MQ伺服器在啟動和執行 rabbitmqctl set_vm_memory_high_watermark fraction的時候會檢測機器上的RAM大小,預設情況下,Rabbit MQ使用記憶體超過40%的時候,會發出記憶體警告,阻塞所有釋出訊息的連線,一旦警告解除(etc,伺服器paging訊息到硬碟或者分發訊息到消費者並且確認)服務會恢復正常。
預設的記憶體閾值是40%,注意,這並不會阻止Rabbit MQ Server使用不到40%,僅僅意味著到達這個點的時候,釋出者會被扼殺,最壞的情況下,Erlang虛擬機器會引起雙倍的記憶體使用(RAM的80%),強烈建議開啟作業系統的SWAP和Page Files。
32位架構每個程序的記憶體限制是2G,一般的64位(AMD或者Interleaving)每個程序允許256T,64位的Windows限制位8T,但是,即使在64位下,32的程序最大可用地址空間也是2G。
配置記憶體閾值
可以通過編輯配置檔案來調整觸發流控的記憶體閾值,下面是把閾值設定位預設值0.4
vm_memory_high_watermark.relative = 0.4
下面是使用經典配置格式:
[{rabbit, [{vm_memory_high_watermark, 0.4}]}].
預設值0.4表示安裝的RAM或者可用虛擬地址空間兩者較小的40%,如果在一個32位機器上,你安裝了4G記憶體,4G的40%是1.6G,但是在32位Windows上,每個程序限制2G,所有閾值實際上是2G的40%(820M).
另外,記憶體閾值可以通過設定一個RAM絕對值來調整,下面的例子把閾值設定位1073741824位元組(1024M)
vm_memory_high_watermark.absolute = 1073741824
相同的例子,但是使用記憶體單位
vm_memory_high_watermark.absolute = 1024MB
使用經典配置格式
[{rabbit, [{vm_memory_high_watermark, {absolute, 1073741824}}]}].
經典格式帶單位
[{rabbit, [{vm_memory_high_watermark, {absolute, "1024MiB"}}]}].
如果這個絕對值比安裝的RAM或者可用虛擬地址空間大,閾值會被設定位較小的。
記憶體限制在Rabbit MQ Server啟動的時候,會被附加到RABBITMQ_NODEHOME.log日誌上。
=INFO REPORT==== 29-Oct-2009::15:43:27 ===
Memory limit set to 2048MB.
在borker執行的時候也可以使用 rabbitmqctl set_vm_memory_high_watermark fraction 命令或者 rabbitmqctl set_vm_memory_high_absolute memory_limit命令,記憶體單位也可以使用,命令會立即生效,直到broker停止,如果broker重新啟動也要生效的話,相應的配置檔案也要改變,在執行此命令但是不改變閾值的情況下,在具有熱交換的RAM系統裡面,閾值可能會變化(因為記憶體總量變了。。)
禁用所有的釋出
設定閾值為0,會立即觸發記憶體警告,阻塞所有的釋出連線(如果你希望禁用全域性釋出,這是非常有用的),使用rabbitmqctl set_vm_memory_high_watermark 0.
有限的地址空間
當在64位機器上執行32位Erlang,地址記憶體是受限制的,伺服器會檢測並列印如下一條訊息:
=WARNING REPORT==== 19-Dec-2013::11:27:13 ===
Only 2048MB of 12037MB memory usable due to limited address space.
Crashes due to memory exhaustion are possible - see
http://www.rabbitmq.com/memory.html#address-space
記憶體警告不是完美的,儘管停止釋出通常會阻止記憶體的進一步使用,但還是有相當大的可能,其它一些東西會繼續提升記憶體的使用,通常,這種情況發生的時候,實體記憶體被耗盡,作業系統會開始交換,但是使用一個受限的地址空間,當超過這個限制的時候,會引起VM的幫虧。
因此強烈建議,在64位OS上執行64位Erlang虛擬機器。
配置Paging閾值
在broker達到high watermark阻塞釋出者之前,它會嘗試通過將佇列的內容page到磁碟來釋放記憶體,持久化和瞬時訊息都會被page out.
預設情況下,在borker達到閾值的50%時(預設記憶體閾值是0.4,當0.2的記憶體被使用時)會發生這種情況。可以通過修改 vm_memory_high_watermark_paging_ration配置來進行修改:
vm_memory_high_watermark_paging_ratio = 0.75
vm_memory_high_watermark.relative = 0.4
使用經典配置:
[{rabbit, [{vm_memory_high_watermark_paging_ratio, 0.75},
{vm_memory_high_watermark, 0.4}]}].
上面的配置會在記憶體使用到04.*0.75=0.3的時候開始paging,在記憶體使用到0.4的時候阻塞釋出者。可以把vm_memory_high_watermark_paging_ratio設定的比1大,在這種情況下,佇列不會把內容page到磁碟,如果引起了記憶體警告,生產者會跟上面解釋的一樣被阻塞。
不識別的平臺
如果Rabbit MQ Server不能識別你的系統,它會在RABBITMQ_NODENAME.log檔案中追加一條資訊,接著它會假設有1GRAM安裝。
=WARNING REPORT==== 29-Oct-2009::17:23:44 ===
Unknown total memory size for your OS {unix,magic_homegrown_os}. Assuming memory size is 1024MB
在這種情況下,vm_memory_high_watermark配置值會使用1G,在使用預設值0.4的時候,RabbitMQ的記憶體閾值是410M,因此當記憶體使用超過410M的時候,它就會扼殺生產者,當Rabbit MQ不識別你的平臺的時候,如果你有8GRAM,你希望閾值設定位0.3在記憶體超過3G的時候來throttle生產者,
磁碟警告
當可用磁碟空間下降到配置值(預設為50M)之下,一個警告會觸發,所有的生產者會被阻塞,目標是避免填充整個磁碟,這會導致節點的寫操作失敗,導致Rabbit MQ中斷,為了減小填充磁碟的風險,所有進來的訊息都會阻塞,在記憶體的壓力下,瞬時的訊息,也會被page到磁碟,將繼續佔用已經到達臨界值的磁碟空間,如果斯潘警告設定的太低,訊息被快速page,有可能在兩次磁碟空間檢查之間填充完整個磁碟,導致Rabbit MQ崩潰(10s),一種更保守的方法是將限制設定為與系統上安裝的記憶體量相同的限制(參見下面的配置)。
如果磁碟可用空間下降到配置值之下,警告會觸發,broker資料庫使用的磁碟或者分割槽的可用空間每10S就會檢測一次,用來決定是否觸發或者清楚警告,監控會從伺服器一啟動的時候就開始,在log file中會增加一條條目:
=INFO REPORT==== 23-Jun-2012::14:52:41 ===
Disk free limit set to 953MB
在不識別的平臺上,監控會禁用,日誌中列印訊息:
=WARNING REPORT==== 23-Jun-2012::15:45:29 ===
Disabling disk free space monitoring
當在叢集中執行Rabbit MQ的時候,磁碟警告也是叢集範圍的,如果一個節點達到限制值之下,所有的節點都會阻塞進來的訊息。
Rabbit MQ會定時檢查可用磁碟空間大小,這個頻率跟上次檢查時可用空間大小相關(以確保在磁碟將要耗盡時,磁碟警告能及時觸發),一般是每10S檢查一下磁碟空間,但是當接近限制值時,頻率會提升,當非常接近的時候檢測會1秒10此,它可能會影響系統的負載。
當可用磁碟空間下降到配置值之下,Rabbit MQ會阻塞生產者,阻止記憶體中的訊息page到磁碟,這會減少磁碟被耗盡而導致崩潰的風險,但是不能完全杜絕。特別是訊息被快速page到磁碟,有可能在兩次磁碟檢查之間用完整個可用空間,保守的做法如下:
配置磁碟可用空間值
磁碟可用空間limit是通過disk_free_limit設定的,預設的50M是為了資料庫分割槽可用,配置檔案設定可用空間為1GB。
disk_free_limit.absolute = 1000000000
加上單位(KB,MB,GB)
disk_free_limit.absolute = 1GB
使用經典的格式
[{rabbit, [{disk_free_limit, 1000000000}]}].
帶單位
也可以設定磁碟可用空間跟機器上的記憶體相關,這個配置設定磁碟可用跟記憶體大小一樣
disk_free_limit.relative = 1.0
經典配置
[{rabbit, [{disk_free_limit, {mem_relative, 1.0}}]}].
這個配置可以在broker執行的時候通過命令rabbitmqctl set_disk_free_limit 大小
或者rabbitmq_disk_free_limit mem_relative 值來使用,這個命令會立即生效,直到broker停止,如果重啟也要生效的話,需要修改配置檔案。
流控
RabbitMQ會降低連線的速度,當傳送太快佇列跟不上的時候,不需要進行配置。
一個流控的連線在rabbitmqctl和管理外掛中會顯示flow狀態,這意味著這個連線每一秒會被阻塞,接觸阻塞好幾次,使訊息的接收速率能匹配上伺服器處理的速率。
一般來說,受流控的連線跟正常執行的是沒什麼不同的,流控狀態來通知sysadmin,傳送速率應該受限,但是從客戶端的角度,它看起來只是伺服器的頻寬比實際低而已。
除了連線,也有一些元件可以處於流控狀態,這篇部落格講述了更多細節:如何使用這些資訊找到伺服器瓶頸。