架構之消息隊列

1. 爲何要用消息隊列?



  假設一個老大,接到一個任務要處理完。在處理這個任務時,把這個任務分解爲幾個小任務,只要分別完成了這幾個小任務,整個任務也就完成了。


  作到某個小任務時,發現這個小任務須要花不少時間完成,並且這個小任務遲點完成也不影響整個任務的完成進度。因而,老大把這個小任務交個一個小弟去作,本身去接着完成其餘的任務。


  在上面的例子中,老大就是後臺系統,小弟就是消息隊列系統,當後臺系統發現完成某些小任務須要花不少時間,並且遲點完成也不影響整個任務的,就會把這些小任務交給消息隊列系統。


  在實際的app後端中,發送郵件,發送短信,推送等這些任務,都很是適合在消息隊列系統中作的。你們想一想,這些任務是否是都須要花比較多的時間,並且遲點完成也不影響的。把這些任務放在隊列中,可加快請求的響應時間。


php

2. 消息隊列是怎麼工做?



  消息隊列系統,通常都包含3個角色:隊列服務端,隊列的生產者,隊列的消費者。


  消息隊列系統相似於這個場景:有一條信息傳送帶不停地運轉。在傳送帶的起點,工人a不斷地把信息放在一個盒子,把盒子放到傳送帶上,盒子被傳送帶傳送到終點。在終點上,工人b把盒子上的信息取出來,進行處理。


  在上面的場景中,不停運轉的傳送帶就是隊列服務端,在傳送帶起點不斷放盒子的工人a就是隊列的生產者,在傳送帶終點不斷取盒子的工人b就是隊列的消費者。


  消息隊列的服務端,如今有大量的開源的應用,例如RabbitMQ ,ZeroMQ ,redis等。


  隊列的生產者和服務者,是針對消息隊列服務端開發的客戶端,例如,RabbitMQ就有針對java,php等語言開發的客戶端。


  例如,在app後端中,用代碼調用 java客戶端,把要發送的短信信息放在ZeroMQ中,這裏java客戶端是充當隊列的生產者。


  寫一個守護進程,在守護進程中,經過代碼調用 java客戶端把要發送的短信信息不斷地從ZeroMQ取出來,而後發送出去。


java

3. 常見的一些消息隊列產品



  RabbitMQ:


  是使用Erlang編寫的一個開源的消息隊列,自己支持不少的協議:AMQP,XMPP, SMTP, STOMP,也正是如此,使的它變的很是重量級,更適合於企業級的開發。同時實現了一個經紀人(Broker)構架,這意味着消息在發送給客戶端時先在中心隊列排隊。對路由(Routing),負載均衡(Load balance)或者數據持久化都有很好的支持。


  同時,RabbitMQ自帶了一個web監控界面,可方便監控隊列的狀況。


  Redis:


  雖然是一個key-value系統,但自身也支持隊列這種數據結構,可看作是一個輕量級的消息隊列系統。


  在app後端架構中,redis是被普遍使用,若是同時把它做爲消息隊列使用,就減小了運維上的成本。


  ZeroMq:


  號稱最快的消息隊列系統,尤爲針對大吞吐量的需求場景。


  ActiveMQ:


web

  是Apache下的一個子項目。 相似於ZeroMQ,它可以以代理人和點對點的技術實現隊列。redis

 

1. 解耦後端

在項目啓動之初來預測未來項目會碰到什麼需求,是極其困難的。消息隊列在處理過程當中間插入了一個隱含的、基於數據的接口層,兩邊的處理過程都要實現這一接口。這容許你獨立的擴展或修改兩邊的處理過程,只要確保它們遵照一樣的接口約束。安全



2. 冗餘數據結構

有時在處理數據的時候處理過程會失敗。除非數據被持久化,不然將永遠丟失。消息隊列把數據進行持久化直到它們已經被徹底處理,經過這一方式規避了數據丟失風險。在被許多消息隊列所採用的"插入-獲取-刪除"範式中,在把一個消息從隊列中刪除以前,須要你的處理過程明確的指出該消息已經被處理完畢,確保你的數據被安全的保存直到你使用完畢。架構

3. 擴展性app

由於消息隊列解耦了你的處理過程,因此增大消息入隊和處理的頻率是很容易的;只要另外增長處理過程便可。不須要改變代碼、不須要調節參數。擴展就像調大電力按鈕同樣簡單。負載均衡



 

4. 靈活性 & 峯值處理能力

當你的應用上了Hacker News的首頁,你將發現訪問流量攀升到一個不一樣尋常的水平。在訪問量劇增的狀況下,你的應用仍然須要繼續發揮做用,可是這樣的突發流量並不常見;若是爲以能處理這類峯值訪問爲標準來投入資源隨時待命無疑是巨大的浪費。使用消息隊列可以使關鍵組件頂住增加的訪問壓力,而不是由於超出負荷的請求而徹底崩潰。

5. 可恢復性

當體系的一部分組件失效,不會影響到整個系統。消息隊列下降了進程間的耦合度,因此即便一個處理消息的進程掛掉,加入隊列中的消息仍然能夠在系統恢復後被處理。而這種容許重試或者延後處理請求的能力一般是造就一個略感不便的用戶和一個沮喪透頂的用戶之間的區別。



6. 送達保證

消息隊列提供的冗餘機制保證了消息能被實際的處理,只要一個進程讀取了該隊列便可。在此基礎上,IronMQ提供了一個"只送達一次"保證。不管有多少進程在從隊列中領取數據,每個消息只能被處理一次。這之因此成爲可能,是由於獲取一個消息只是"預約"了這個消息,暫時把它移出了隊列。除非客戶端明確的表示已經處理完了這個消息,不然這個消息會被放回隊列中去,在一段可配置的時間以後可再次被處理。

 

7.排序保證

在許多狀況下,數據處理的順序都很重要。消息隊列原本就是排序的,而且能保證數據會按照特定的順序來處理。IronMO保證消息漿糊經過FIFO(先進先出)的順序來處理,所以消息在隊列中的位置就是從隊列中檢索他們的位置。

8.緩衝

在任何重要的系統中,都會有須要不一樣的處理時間的元素。例如,加載一張圖片比應用過濾器花費更少的時間。消息隊列經過一個緩衝層來幫助任務最高效率的執行--寫入隊列的處理會盡量的快速,而不受從隊列讀的預備處理的約束。該緩衝有助於控制和優化數據流通過系統的速度。

 

9. 理解數據流

在一個分佈式系統裏,要獲得一個關於用戶操做會用多長時間及其緣由的整體印象,是個巨大的挑戰。消息系列經過消息被處理的頻率,來方便的輔助肯定那些表現不佳的處理過程或領域,這些地方的數據流都不夠優化。

10. 異步通訊

不少時候,你不想也不須要當即處理消息。消息隊列提供了異步處理機制,容許你把一個消息放入隊列,但並不當即處理它。你想向隊列中放入多少消息就放多少,而後在你樂意的時候再去處理它們。

 

 

點擊連接加入羣【.NET大型網站架構】433685124QQ羣