說到rabbitMQ,就不得不提下AMQP(advanced Message Queuing Protocol)高級消息隊列協議。redis
AMQP是一個提供統一消息服務的應用層標準高級消息隊列協議,是應用層協議的一個開放標準,爲面向消息的中間件而設計的。基於此協議的客戶端與消息中間件可傳遞消息,並不受客戶端/中間件不一樣產品,不一樣的開發語言等條件的限制。消息中間件主要用於組件之間的解耦,消息的發送者無需知道消息使用者的存在,反之亦然。算法
上圖即AMQP消息隊列的模型。數據庫
Publisher即消息的生產者,消息生產者負責生產消息併發布到消息隊列中。編程
Consumer即消息的消費者,消費者負責從消息隊列中取出消息,並對消息作相應的處理。緩存
中間大矩形中的全部能夠理解成一個消息隊列服務器。安全
AMQP是一個協議標準,一個規範,rabbitMQ是具體的實現。服務器
##爲何要使用消息隊列。 剛接觸消息隊列的人可能會有一些誤解。網絡
前面也說了,amqp最大的特色是解耦,不一樣系統,不一樣編程語言之間能夠通行協同工做。其次就可拓展的靈活性,由於消息隊列解耦了你的處理過程,把消息發佈與消息處理分離。那消息分發的靈活性,消息處理頻率的靈活性便可很好的調節。併發
####總結使用消息隊列的好處以下:負載均衡
一、解耦。在項目啓動之初來預測未來項目會碰到什麼需求,是極其困難的。消息隊列在處理過程當中間插入了一個隱含的、基於數據的接口層,兩邊的處理過程都要實現這一接口。這容許你獨立的擴展或修改兩邊的處理過程,只要確保它們遵照一樣的接口約束。
二、冗餘。有時在處理數據的時候處理過程會失敗。除非數據被持久化,不然將永遠丟失。消息隊列把數據進行持久化直到它們已經被徹底處理,經過這一方式規避了數據丟失風險。在被許多消息隊列所採用的"插入-獲取-刪除"範式中,在把一個消息從隊列中刪除以前,須要你的處理過程明確的指出該消息已經被處理完畢,確保你的數據被安全的保存直到你使用完畢。
三、擴展性。由於消息隊列解耦了你的處理過程,因此增大消息入隊和處理的頻率是很容易的;只要另外增長處理過程便可。不須要改變代碼、不須要調節參數。擴展就像調大電力按鈕同樣簡單。
四、靈活性 & 峯值處理能力。當你的應用上了Hacker News的首頁,你將發現訪問流量攀升到一個不一樣尋常的水平。在訪問量劇增的狀況下,你的應用仍然須要繼續發揮做用,可是這樣的突發流量並不常見;若是爲以能處理這類峯值訪問爲標準來投入資源隨時待命無疑是巨大的浪費。使用消息隊列可以使關鍵組件頂住增加的訪問壓力,而不是由於超出負荷的請求而徹底崩潰。請查看咱們關於峯值處理能力的博客文章瞭解更多此方面的信息。
五、可恢復性。當體系的一部分組件失效,不會影響到整個系統。消息隊列下降了進程間的耦合度,因此即便一個處理消息的進程掛掉,加入隊列中的消息仍然能夠在系統恢復後被處理。而這種容許重試或者延後處理請求的能力一般是造就一個略感不便的用戶和一個沮喪透頂的用戶之間的區別。
六、送達保證。消息隊列提供的冗餘機制保證了消息能被實際的處理,只要一個進程讀取了該隊列便可。在此基礎上,IronMQ提供了一個"只送達一次"保證。不管有多少進程在從隊列中領取數據,每個消息只能被處理一次。這之因此成爲可能,是由於獲取一個消息只是"預約"了這個消息,暫時把它移出了隊列。除非客戶端明確的表示已經處理完了這個消息,不然這個消息會被放回隊列中去,在一段可配置的時間以後可再次被處理。
七、異步通訊。不少時候,你不想也不須要當即處理消息。消息隊列提供了異步處理機制,容許你把一個消息放入隊列,但並不當即處理它。你想向隊列中放入多少消息就放多少,而後在你樂意的時候再去處理它們
八、排序保證。在許多狀況下,數據處理的順序都很重要。消息隊列原本就是排序的,而且能保證數據會按照特定的順序來處理。IronMO保證消息漿糊經過FIFO(先進先出)的順序來處理,所以消息在隊列中的位置就是從隊列中檢索他們的位置
九、緩衝。在任何重要的系統中,都會有須要不一樣的處理時間的元素。例如,加載一張圖片比應用過濾器花費更少的時間。消息隊列經過一個緩衝層來幫助任務最高效率的執行--寫入隊列的處理會盡量的快速,而不受從隊列讀的預備處理的約束。該緩衝有助於控制和優化數據流通過系統的速度。
十、 理解數據流。在一個分佈式系統裏,要獲得一個關於用戶操做會用多長時間及其緣由的整體印象,是個巨大的挑戰。消息系列經過消息被處理的頻率,來方便的輔助肯定那些表現不佳的處理過程或領域,這些地方的數據流都不夠優化。
消息隊列運做能夠理解成收發快遞的運做。 消息發佈者至關於發件人;消息的消費者至關於收件人;整個快遞公司至關於消息隊列的服務器;快遞員至關消息隊列服務器中的消息隊列。
####AMQP中的幾個對象以下:
1.publisher。 消息的發佈者。發件人 2.Consumer。 消息的消費者。 收件人 3.Exchange。 交換機。這兒能夠理解爲快遞點,負責把消息(快遞)分發到對應的queue(快遞員)中。 5.Queue。 用來存儲消息的隊列(快遞員)。
####AMQP中的幾個概念
1.Binding。 綁定,是把Exchange和queue之聯繫起來。binding key就是聯繫的規則。這兒能夠把Exchange理解爲快遞點,queue能夠理解爲快遞員。binding就是快遞點和快遞員之間的協商,快遞員負責的哪一片區域。binding key能夠理解爲快遞員負責的區域。 2.binding key。 Exchange和queue之間的鏈接規則,快遞員負責的區域。 3.routing key。消息生產者生產的消息中攜帶的Exchange到queue之間的規則。這兒能夠理解爲快遞中的具體地址,是屬於每個消息(快遞包裹)的屬性。binding key是Exchange和queue之間的關係。基本上binding key和routing key的做用是相同,沒多大卻別。 4.Message acknowledgment。 消息確認回執。即消費者收到消息後,給消息隊列服務器的確認回執,相似於快遞迴執單。 5.Message durability。 消息的持久化,在系統宕機後,能夠恢復沒出來完的消息。 6.Prefetch count。預取消息。在多個消費者共享一個隊列的案例中,明確指定在收到下一個確認回執前每一個消費者一次能夠接受多少條消息是很是有用的。
交換機是用來發送消息的AMQP實體。交換機拿到一個消息以後將它路由給一個或零個隊列。它使用哪一種路由算法是由交換機類型和被稱做綁定(bindings)的規則所決定的。AMQP 0-9-1的代理提供了四種交換機
Name(交換機類型) | Default pre-declared names(預聲明的默認名稱) | 說明 |
---|---|---|
Direct exchange(直連交換機) | (Empty string) and amq.direct | routing key必須和binding key徹底匹配 |
Fanout exchange(扇型交換機) | amq.fanout | binding key無效,Exchange會把消息發送到全部bind到該Exchange的queue |
Topic exchange(主題交換機) | amq.topic | binding key與routing key只須要一個匹配上,即會轉發消息 |
Headers exchange(頭交換機) | amq.match (and amq.headers in RabbitMQ) | 使用消息的屬性進行匹配,binding key不起做用 |
除交換機類型外,在聲明交換機時還能夠附帶許多其餘的屬性,其中最重要的幾個分別是: |
交換機能夠有兩個狀態:持久(durable)、暫存(transient)。持久化的交換機會在消息代理(broker)重啓後依舊存在,而暫存的交換機則不會(它們須要在代理再次上線後從新被聲明)。然而並非全部的應用場景都須要持久化的交換機。
默認交換機(default exchange)其實是一個由消息代理預先聲明好的沒有名字(名字爲空字符串)的直連交換機(direct exchange)。它有一個特殊的屬性使得它對於簡單應用特別有用處:那就是每一個新建隊列(queue)都會自動綁定到默認交換機上,綁定的鍵(binding key)名稱與隊列名稱相同。默認交換機能夠理解成一個特殊的直連交換機。
直連型交換機(direct exchange)是根據消息攜帶的路由鍵(routing key)將消息投遞給對應隊列的。直連交換機用來處理消息的單播路由(unicast routing)(儘管它也能夠處理多播路由)。下邊介紹它是如何工做的:
直連型交換機圖例:
扇型交換機(funout exchange)將消息路由給綁定到它身上的全部隊列,而不理會綁定的路由鍵。若是N個隊列綁定到某個扇型交換機上,當有消息發送給此扇型交換機時,交換機會將消息的拷貝分別發送給這全部的N個隊列。扇型用來交換機處理消息的廣播路由(broadcast routing)。
由於扇型交換機投遞消息的拷貝到全部綁定到它的隊列,因此他的應用案例都極其類似:
扇型交換機圖例:
有時消息的路由操做會涉及到多個屬性,此時使用消息頭就比用路由鍵更容易表達,頭交換機(headers exchange)就是爲此而生的。頭交換機使用多個消息屬性來代替路由鍵創建路由規則。經過判斷消息頭的值可否與指定的綁定相匹配來確立路由規則。
咱們能夠綁定一個隊列到頭交換機上,並給他們之間的綁定使用多個用於匹配的頭(header)。這個案例中,消息代理得從應用開發者那兒取到更多一段信息,換句話說,它須要考慮某條消息(message)是須要部分匹配仍是所有匹配。上邊說的「更多一段消息」就是"x-match"參數。當"x-match"設置爲「any」時,消息頭的任意一個值被匹配就能夠知足條件,而當"x-match"設置爲「all」的時候,就須要消息頭的全部值都匹配成功。
頭交換機能夠視爲直連交換機的另外一種表現形式。頭交換機可以像直連交換機同樣工做,不一樣之處在於頭交換機的路由規則是創建在頭屬性值之上,而不是路由鍵。路由鍵必須是一個字符串,而頭屬性值則沒有這個約束,它們甚至能夠是整數或者哈希值(字典)等。
消息隊列是用來緩存消息。 由Exchange把消息推送到queue中。
持久化隊列(Durable queues)會被存儲在磁盤上,當消息代理(broker)重啓的時候,它依舊存在。沒有被持久化的隊列稱做暫存隊列(Transient queues)。並非全部的場景和案例都須要將隊列持久化。
持久化的隊列並不會使得路由到它的消息也具備持久性。假若消息代理掛掉了,從新啓動,那麼在重啓的過程當中持久化隊列會被從新聲明,不管怎樣,只有通過持久化的消息才能被從新恢復。
綁定(Binding)是交換機(exchange)將消息(message)路由給隊列(queue)所需遵循的規則。若是要指示交換機「E」將消息路由給隊列「Q」,那麼「Q」就須要與「E」進行綁定。綁定操做須要定義一個可選的路由鍵(routing key)屬性給某些類型的交換機。路由鍵的意義在於從發送給交換機的衆多消息中選擇出某些消息,將其路由給綁定的隊列。 打個比方: