RabbitMq 性能調優筆記

避免雷區

要避免流控機制觸發

  • 服務端默認配置是當內存使用達到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適當的限制連接

來源:https://segmentfault.com/a/1190000016351345?utm_source=tag-newest

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章