RabbitMq 最全的效能調優筆記

石志遠發表於2019-01-19

RabbitMq 效能調優筆記

[TOC]

避免雷區

要避免流控機制觸發

  • 服務端預設配置是當記憶體使用達到40%,磁碟空閒空間小於50M,即啟動記憶體報警,磁碟報警;報警後服務端觸發流控(flowcontrol)機制。
  • 一般地,當釋出端傳送訊息速度快於訂閱端消費訊息的速度時,佇列中堆積了大量的訊息,導致報警,就會觸發流控機制。
  • 觸發流控機制後,RabbitMQ服務端接收發布來的訊息會變慢,使得進入佇列的訊息減少
  • 與此同時RabbitMQ服務端的訊息推送也會受到極大的影響,測試發現,服務端推送訊息的頻率會大幅下降,等待下一次推送的時間,有時等1分鐘,有時5分鐘,甚至30分鐘。
  • 一旦觸發流控,將導致RabbitMQ服務端效能惡化,推送訊息也會變得非常緩慢;
  • 因此要做好資料設計,使得傳送速率和接收速率保持平衡,而不至於引起伺服器堆積大量訊息,進而引發流控。通過增加伺服器叢集節點,增加消費者,來避免流控發生,治標不治本,而且成本高。
  • 伺服器單節點,單網路卡全雙工情況下,測試發現釋出速度過快,壓滿釋出PC機頻寬,對於伺服器來說,下行(接收)頻寬也會壓滿,可是上行(轉發遞送)頻寬卻出現了明顯的下降,似乎有一個爭搶。這可能是導致觸發流控的原因。

從底層取資料一定要非常及時

訂閱端每隔500MS呼叫一次amqp_consume_message介面函式從socket上獲取資料,正常情況下,伺服器每次會推送幾百條訊息,而且推送的頻率會比較高;

導致訂閱端的本機socket緩衝區會很快存滿,導致很多訊息無法進行快取,而被丟掉;

釋出訊息條數 呼叫amqp_comsume_message間隔(MS) 實際接收條數
630 500 269
695 470 269
513 460 269
503 450 503

訊息大小不要超過4MB

  • 客戶端與RabbitMQ服務端的最大幀是128K,但訊息大小卻可支援數MB,這是可能是因為底層做了拆包組包的,目前我還未檢視底層程式碼。
  • 用執行緒來模擬50個釋出者和50個訂閱者;

訊息包大小由1K到10MB,當包大小達到4.5MB時,伺服器的效能出現明顯的異常,傳輸率尤其是每秒訂閱訊息的數量,出現波動,不穩定;同時有一部分訂閱者的TCP連線出現斷開的現象。可能是客戶端底層或者RabbitMQ服務端在進行拆包,組包的時候,出現了明顯的壓力,而導致異常的發生。

  • 超過4MB的訊息,最好先進行分包

consume時預取引數的大小對consume效能影響很大

具體可參見官方部落格

磁碟也可能形成瓶頸

磁碟也可能形成瓶頸,如果單臺機器佇列很多,確認只在必要時才使用duration(持久化),避免把磁碟跑滿;

佇列的訊息大量累積後

佇列的訊息大量累積後,傳送和消費速度都會受到影響,導致服務進一步惡化,採用的方法是,額外的指令碼監控每個佇列的訊息數,超過限額會執行purge操作,簡單粗暴但是有效的保證了服務穩定;

調優

單機限制

由於用執行緒模擬大量釋出者,且是伺服器單節點,受客戶端主機網路卡的限制,釋出執行緒沒有速度控制,導致有大量資料傳送,伺服器頻寬下行速率也滿負荷,上行頻寬卻明顯低於下行速率,導致伺服器記憶體有大量訊息堆積,進而觸發RabbitMQ伺服器paging操作,才出現了上述不穩定和訂閱者斷開現象。

對釋出端做適當流量控制,斷開連線現象不再出現,但每秒訊息數仍然不穩定

模式對效能的影響

分析三種模式 direct fanout topic

不同的模式對於新建交換機、新建佇列、繫結等操作效能影響不大,

但是在direct模式下明顯訊息釋出的效能比其他模式強很多,並且訊息傳送到相同佇列比傳送到不同佇列效能稍好

持久化對訊息效能的影響

在訊息持久化模式下:

釋出:13888msg/s 
訂閱:15384msg/s

在訊息非持久化模式下:

釋出:18867msg/s 
訂閱:26315msg/s

問題分析/解決方案

問題分析:

可以看到RabbitMQ的記憶體 佔用佔用已經使用了7.8G 允許的值為 .6G左右

因為 vm_memory_high_watermark 值設定的是0.4 也就是實體記憶體的40% ;伺服器為16G * 40% = 6.4G

一般在產生的原因是長期的生產者傳送速率大於消費者消費速率導致. 觸發了RabbitMQ 的流控;

解決方案:

  1. 增加消費者端的消費能力,或者增加消費者(根本解決)
  2. 控制訊息產生者端的傳送速率(不太現實)
  3. 增加mq的記憶體(治標不治本)

引數調優

vm_memory_high_watermark:用於配置記憶體閾值,建議小於0.5,因為Erlang GC在最壞情況下會消耗一倍的記憶體。

vm_memory_high_watermark_paging_ratio:用於配置paging閾值,該值為1時,直接觸發記憶體滿閾值,block生產者。

IO_THREAD_POOL_SIZE:CPU大於或等於16核時,將Erlang非同步執行緒池數目設為100左右,提高檔案IO效能。

hipe_compile:開啟Erlang HiPE編譯選項(相當於Erlang的jit技術),能夠提高效能20%-50%。在Erlang R17後HiPE已經相當穩定,RabbitMQ官方也建議開啟此選項。

queue_index_embed_msgs_below:RabbitMQ 3.5版本引入了將小訊息直接存入佇列索引(queue_index)的優化,訊息持久化直接在amqqueue程式中處理,不再通過msg_store程式。由於訊息在5個內部佇列中是有序的,所以不再需要額外的位置索引(msg_store_index)。該優化提高了系統效能10%左右。

queue_index_max_journal_entries:journal檔案是queue_index為避免過多磁碟定址新增的一層緩衝(記憶體檔案)。對於生產消費正常的情況,訊息生產和消費的記錄在journal檔案中一致,則不用再儲存;對於無消費者情況,該檔案增加了一次多餘的IO操作。

最佳執行緒

  • 生產者使用多執行緒傳送資料到queue三到五個執行緒效能傳送最佳,超過它也不能提高生產的傳送速率。
  • 消費者的資料處理,使用二執行緒接收效能是最佳的,如資料處理程式處理比較複雜的邏輯,建議多開啟幾個執行緒進行資料接收。
  • 在傳送接收佇列中,因為傳送的速率總比接收的速率要快,因此考慮在接收端配置比傳送端更多的執行緒,個人認為:接收者執行緒 = 傳送者執行緒 X 1.5

資料恢復

  • RabbitMq在做資料恢復時,遇到過一次資料恢復不了後就沒有辦法復現。資料恢復的時間會隨著資料量的大小成直線增長。

叢集

沒測

用iptables適當的限制連線

相關文章