摘要:本篇是本人對RabbitMQ使用的關鍵性問題進行的總結,如性能上限、數據存儲、集群等,
具體的RabbitMQ概念、安裝、使用方法、SpringAMQP配置,假設讀者已有了基礎。
1. RabbitMQ
1.1 RabbitMQ數據速率問題
在邊讀邊寫的情況下:速率只與網絡帶寬正相關,網絡使用率最高能達到接近100%,並且數據使用率很高(90%以上)。
在千兆網下,以500KB一條數據為例,讀寫速率均能達到200條/s,約為100MB/s。
在只寫不讀的情況下:寫入速率瓶頸在於硬盤寫入速度。
1.2 RabbitMQ數據存儲路徑變更到D盤方法
Windows環境下,在安裝前設置環境變量:RABBITMQ_BASE=D:\RabbitMQ_Data
1.3 RabbitMQ磁盤寫滿重啟后數據丟失問題
表現:磁盤寫滿后發送、讀取程序均不能連接服務。
解決方法:將Queue、Exchange設置為Durable即不會發生數據丟失問題。
通過a.關閉服務;b.刪除占位文件、erl_crash.dump;c.重啟服務 三步操作后,磁盤會清理出10M左右空間,此時讀取數據程序便可正常工作。
正確設計的架構,應確保RabbitMQ不會發生磁盤寫滿崩潰的情況。
1.4 RabbitMQ集群
在網絡帶寬占滿的情況下,通過集群的方式解決吞吐量不足的問題需要多台效果才明顯。

假設外設吞吐率為d條/s,外設向RabbitMQ1發送的概率為r1,向RabbitMQ2發送的概率為r2,RabbitMQ1需要向RabbitMQ2轉發的概率為r3,RabbitMQ2需要向RabbitMQ1轉發的概率為r3。那么RabbitMQ1進入的吞吐率為:(r1*d + r4*r2*d) 條/s ≈ 3d/4條/s,RabbitMQ2進入的吞吐率為:(r2*d + r3*r1*d) 條/s ≈ 3d/4條/s;這樣的確比只使用一台RabbitMQ的吞吐率d條/s要求低些。
N台RabbitMQ的集群,每台的平均吞吐率為:(2N-1)d/(N*N) 條/s;N=3時,平均吞吐率為5d/9條/s;N=4時,平均吞吐率為7d/16條/s。
解決方法:多台RabbitMQ服務器提供服務,在客戶端以輪循方式訪問服務,若1台down掉則不使用此台的隊列服務,服務器之間沒有聯系,這樣N台RabbitMQ的平均吞吐率為:1d/N 條/s。具體實現可以,專寫一個用戶收發RabbitMQ消息的jar/dll,在配置文件里填寫RabbitMQ機器地址,使用輪循詢問、收發的方式,提供給應用程序以黑盒方式調用。下面提供了java版本的收發實現。
發送端sender.xml配置:
|
<!-- 處理器相關 -->
<bean id="sender" class="demo.Sender">
<property name="templates">
<list>
<ref bean="template1" />
<!-- <ref bean="template2" /> -->
</list>
</property>
</bean>
<bean id="timeFlicker" class="demo.TimeFlicker">
<property name="handlers">
<list>
<ref bean="sender" />
</list>
</property>
</bean>
<!-- 處理器相關 -->
<!-- amqp配置 相關 -->
<rabbit:connection-factory id="connectionFactory1"
host="192.1.11.108" username="guest" password="guest" virtual-host="/" />
<rabbit:connection-factory id="connectionFactory2"
host="192.1.11.172" username="guest" password="guest" virtual-host="/" />
<!-- amqp配置 相關 -->
<!-- 發送相關 -->
<rabbit:template id="template1" connection-factory="connectionFactory1"
exchange="exchange" />
<rabbit:template id="template2" connection-factory="connectionFactory2"
exchange="exchange" />
<!-- 發送相關 --> |
說明:這里配置了兩個RabbitMQ服務器,timeFlicker的目的是過一段時間把不能服務的RabbitMQ服務器重新添加到列表中,重試發送。
接收端receiver.xml配置:
|
<!-- amqp配置 相關 -->
<rabbit:connection-factory id="connectionFactory1"
host="192.1.11.108" username="guest" password="guest" virtual-host="/" />
<rabbit:connection-factory id="connectionFactory2"
host="192.1.11.172" username="guest" password="guest" virtual-host="/" />
<!-- amqp配置 相關 -->
<!-- 監聽相關 -->
<bean id="Recv1" class="demo.Recv1" />
<rabbit:listener-container id="Listener1"
connection-factory="connectionFactory1" prefetch="1" acknowledge="auto">
<rabbit:listener ref="Recv1" method="listen"
queue-names="queue1" />
</rabbit:listener-container>
<bean id="Recv2" class="demo.Recv2" />
<rabbit:listener-container id="Listener"
connection-factory="connectionFactory1" prefetch="1" acknowledge="auto">
<rabbit:listener ref="Recv2" method="listen"
queue-names="queue2" />
</rabbit:listener-container>
<!-- 監聽相關 -->
|
說明:這里監聽了兩個RabbitMQ服務器,此處不需要timeFlicker。
如需具體代碼可以聯系本人 http://www.cnblogs.com/wgp13x/。
我認為MQ丟數據的問題,主要是同步還是異步刷盤、斷電是否導致的。只要send反饋正確,確保發送被接收,receive時有反饋后才會刪除數據;同步刷盤,或異步刷盤不斷電的,就不會丟失消息,
程序對於發送反饋異常的,要記錄;MQ對於receive無反饋的,有重發機制,可能會有一條數據發送多次的情況,要在程序中剔除。
