MQ見解


MQ

  消息隊列是系統級、模塊級的通信。RPC是對象級、函數級通信。  

1) 什么是推模式,什么是拉模式

2) 有沒有消息丟失情況,如何防止

3) MQ用來解決什么問題

4) 你們用的什么MQ,為什么要用這個,它的最大吞吐量是多少

AcitveMQ是作為一種消息存儲和分發組件

  ActiveMQ默認的使用的協議是openWire,端口號:61616
  一條消息從producer端發出之后,一旦被broker正確保存,那么它將會被consumer消費,然后ACK,broker端才會刪除;不過當消息過期或者存儲設備溢出時,也會終結它

持久化
  非持久化消息是存儲在內存中的,持久化消息是存儲在文件中的
ActiveMQ會將內存中的非持久化消息寫入臨時文件中,以騰出內存。雖然都保存到了文件里,但它和持久化消息的區別是,重啟后持久化消息會從文件中恢復,非持久化的臨時文件會直接刪除
  設置2G左右的持久化文件限制,大量生產持久化消息直到文件達到最大限制,此時生產者阻塞,但消費者可正常連接並消費消息,等消息消費掉一部分,文件刪除又騰出空間之后,生產者又可繼續發送消息,服務自動恢復正常。

  設置2G左右的臨時文件限制,大量生產非持久化消息並寫入臨時文件,在達到最大限制時,生產者阻塞,消費者可正常連接但不能消費消息,或者原本慢速消費的消費者,消費突然停止。整個系統可連接,但是無法提供服務,就這樣掛了。

  解決方案:盡量不要用非持久化消息,非要用的話,將臨時文件限制盡可能的調大

死信隊列
  一條消息不能正常處理.重發給其他服務器處理依舊不能處理.重試6次(重試次數可配置)后MQ就把這條消息放到死信隊列

optimizeACK(可優化的ACK 延遲確認”的語義(ACK時機))和 prefethSize(批量預獲取(默認1000))
  optimizeACK時機 () optimizeACK優化了消息確認的性能
    只有當session的ACK_MODE為AUTO_ACKNOWLEDGE時才會生效 client端在消費消息后暫且不發送ACK,而是把它緩存下來(pendingACK),等到這些消息的條數達到一定閥值時,只需要通過一個ACK指令把它們全部確認;這比對每條消息都逐個確認,在性能上要提高很多

    optimizeACK有效時,如果客戶端已經消費但尚未確認的消息(deliveredMessage)達到prefetch * 0.65,consumer端將會自動進行ACK;同時如果離上一次ACK的時間間隔,已經超過"optimizeAcknowledgeTimout"毫秒,也會導致自動進行ACK。
    prefetchACK為true,那么prefetch必須大於0;當prefetchACK為false時,你可以指定prefethSize為0以及任意大小的正數


prefethSize(默認1000) prefethSize優化了消息傳送的性能
  批量獲取消息,並“延遲”確認(ACK)。prefethSize表達了“批量獲取”消息的語義,broker端主動的批量push多條消息給client端,總比client多次發送PULL指令然后broker返回一條消息的方式要優秀很多,它不僅減少了client端在獲取消息時阻塞的次數和阻塞的時間,還能夠大大的減少網絡開支

  prefethSize=0時,表示consumer將使用PULL(拉取)的方式從broker端獲取消息,broker端將不會主動push消息給client端,直到client端發送PullCommand時

  當prefethSize=>0時,表示consumer將接受broker端PUSh(推送)的方式獲取消息,此后只要當client端消費且ACK了一定的消息之后,會立即push給client端多條消息

 

consumer獲取消息的方式
  使用receive()方法同步獲取消息
    prefethSize可以為0和任意正值;當prefethSize=0時,那么receive()方法將會首先發送一個PULL指令並阻塞,直到broker端返回消息為止,這也意味着消息只能逐個獲取(類似於Request<->Response),這也是Activemq中PULL消息模式;當prefethSize > 0時,broker端將會批量push給client 一定數量的消息(<= prefethSize),client端會把這些消息(unconsumedMessage)放入到本地的隊列中,只要此隊列有消息,那么receive方法將會立即返回,當一定量的消息ACK之后,broker端會繼續批量push消息給client端


使用MessageListener異步獲取消息
  這就需要開發設定的prefethSize值必須 >=1,即至少為1;在異步消費消息模式中,設定prefethSize=0,是相悖的,也將獲得一個Exception
  消息的確認是在onMessage方法返回之后,如果onMessage方法異常,會導致消息不能被ACK,會觸發重發

consumer的消費能力
  如果consumer端消費速度很慢(對消息的處理是耗時的) 過大的prefetchSize,並不能有效的提升性能,反而不利於consumer端的負載均衡(只針對queue),使用較小的prefetchSize,同時關閉optimizeACK,可以讓消息在多個consumer間“負載均衡”
  如果較大的prefetchSize,將會導致broker一次性push給client大量的消息,但是這些消息需要很久才能ACK(消息積壓),而且在client故障時,還會導致這些消息的重發

  如果consumer端消費速度很快,但是producer端生成消息的速率較慢 .開啟optimizeACK,但是需要設置較小的prefetchSize;這樣可以保證每個consumer都能有"活干",否則將會出現一個consumer非常忙碌,但是其他consumer幾乎收不到消息。

  如果消息很重要,那么我們需要將optimizeACK=false,prefetchSize=1
  總之消費端要對重復消息做冪等控制,在消息被消費之后還沒有來得及確認時,client端發生故障,那么這些消息就有可能會被重新發送給其他consumer

ACK模式
JMS API中約定了Client端可以使用四種ACK_MODE,在javax.jms.Session接口中:
AUTO_ACKNOWLEDGE = 1 自動確認
CLIENT_ACKNOWLEDGE = 2 客戶端手動確認 
DUPS_OK_ACKNOWLEDGE = 3 自動批量確認
SESSION_TRANSACTED = 0 事務提交並確認

INDIVIDUAL_ACKNOWLEDGE = 4 單條消息確認(AcitveMQ補充了一個自定義的ACK_MODE)

ActiveMQ中定義了如下幾種ACK_TYPE(參看MessageAck類):

    • DELIVERED_ACK_TYPE = 0    消息"已接收",但尚未處理結束
    • STANDARD_ACK_TYPE = 2    "標准"類型,通常表示為消息"處理成功",broker端可以刪除消息了
    • POSION_ACK_TYPE = 1    消息"錯誤",通常表示"拋棄"此消息,比如消息重發多次后,都無法正確處理時,消息將會被刪除或者DLQ(死信隊列)
    • REDELIVERED_ACK_TYPE = 3    消息需"重發",比如consumer處理消息時拋出了異常,broker稍后會重新發送此消息
    • INDIVIDUAL_ACK_TYPE = 4    表示只確認"單條消息",無論在任何ACK_MODE下    
    • UNMATCHED_ACK_TYPE = 5    在Topic中,如果一條消息在轉發給“訂閱者”時,發現此消息不符合Selector過濾條件,那么此消息將 不會轉發給訂閱者,消息將會被存儲引擎刪除(相當於在Broker上確認了消息)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM