RabbitMQ基本概念
AMQP 和IM的區別:
AMQP: ?
1、可以一對多廣播,也可以一對一廣播
2、生產者和消費者不知道對方是誰
IM:
1、只能一對一廣播
2、生產者和消費者知道對方是誰
RabbitMQ:只是消息代理
-
我們不生產消息,我們只是消息的搬運工
-
每條消息只會發送給一個訂閱者(一個蘿卜一個坑)
消息的傳遞過程:
生產者==>MQ==>消費者
消息
-
有效載荷:需要傳輸的數據內容本身
-
標簽:用來告訴Rabbit消息應該投遞給誰
MQ的相關概念
-
交換器:用于接收生產者發送過來的消息 ? ?
-
隊列:用來存儲生產者發送過來的消息,供消費者消費,可以理解為裝消息的容器
-
綁定:用來決策交換器將消息發送到哪個隊列上
如果用乘坐火車打比方,可以這樣理解RabbitMQ
乘客是消息,火車站進站安檢口相當于交換器,負責接收乘客,并告訴乘客自己應該到哪個檢票口等候
檢票口排隊的乘客相當于隊列,乘坐同一班次列車的乘客在同一個檢票口檢票進站
乘客的手上的火車票相當于綁定(路由鍵),用來告訴乘客該坐哪一班次的列車,該從哪一個檢票口進站。
火車車廂里的每一個座位就相當于消費者,一個座位只能給一個乘客坐
隊列
什么是隊列?
隊列(Queues)是你的消息(messages)的終點,可以理解成裝消息的容器。消息就一直在里面,直到有客戶端(也就是消費者,Consumer)連接到這個隊列并且將其取走為止
隊列相關命令:
basic.consume:持續訂閱消息,將信道設置為接受模式。消息一到達隊列,消費者就接收消息,可以持續接收多條消息
basic.get:訂閱單條消息,接收消息后,取消訂閱。這樣做是為了讓消費者只接收下一條消息,如果想獲得更多消息,需要再次發送basic.get。
basic.ack:消費者接收消息后,向RabbitMQ發送確認,表示已經收到消息
auto_ack:消費者在訂閱隊列是如果設置為auto_ack,表示消費者一旦接收消息后,RabbitMQ自動默認為消費者確認收到了消息。
basic.reject:消費者拒絕接收MQ發送過來的消息。RabbitMQ2.0版本后新增的命令
requeue:
true:如果requeue參數設置為true,則RabbitMQ將消息重新發送給下一位消費者
false:如果設置為false,則RabbitMQ將消息從隊列移除
queue.declare:創建隊列,如果不指定隊列名稱,則Rabbit會分配一個隨機名稱,并在命令的響應中返回
exclusive:如果設置為true,列隊變為私有的,即一個隊列只有一個消費者
aotu-delete:當最后一個消費者取消訂閱后,隊列會自動移除。如果需要臨時創建一個隊列,可以結合exclusive使用。消費者斷開連接時,隊列自動移除
隊列工作原理
多個消費者訂閱同一隊列時,怎么發送消息?
消費者A和B同時訂閱了seed_bin隊列
1、消息Message_A到達隊列seed_bin
2、RabbitMQ把Message_A發送給A
3、A確認接收到了消息Mesage_A
4、RabbitMQ將消息Message_A從隊列seed_bin刪除
5、消息Message_B到達隊列seed_bin
6、RabbitMQ把Message_B發送給B
7、B確認接收到了消息Mesage_B
8、RabbitMQ將消息Message_B從隊列seed_bin刪除
注意:
如果消費者收到一條消息后,從RabbiMQ隊列斷開了(或者說取消了訂閱),一直沒有發送確認。那么MQ認為這條消息沒有發送,然后會重新將該消息發送給下一位消費者。這樣做的好處是如果接收消息的程序出現問題,或者有bug,導致沒有發送確認,這樣RabbitMQ不會再給該應用發送消息。因為RabbitMQ會認為你的程序還沒有準備好接收下一條消息,這樣可以防止消息源源不斷的涌向你的應用,到導致過載。
交換器
什么是交換器?
交換器是服務器接收到生產者發送過來的消息后,根據不同的規則,將消息投遞到不同的隊列的工具。這些規則被稱為路由鍵。隊列是通過路由鍵綁定到交換器的。當生產者將消息發給RabbitMQ代理服務器時,消息將擁有一個路由鍵,Rabbit會將其與綁定的路由鍵踐行匹配,如果匹配則投遞到該隊列,如果匹配不到任何綁定模式,則消息進入黑洞。
交換器的類型
-
direct:如果路由鍵匹配,則直接投遞到對應的隊列
-
fanout:不處理路由鍵,向所有與之綁定的隊列投遞消息
-
topic:處理路由鍵,按模式匹配,向符合規則的隊列投遞消息
-
headers:允許匹配消息的header,而非路由鍵,除此之外,direct完全一致,但性能差很多,基本不用了。
direct:
?處理路由鍵。需要將一個隊列綁定到交換機上,要求該消息與一個特定的路由鍵完全匹配。這是一個完整的匹配。如果一個隊列綁定到該交換機上要求路由鍵?“dog”,則只有被標記為“dog”的消息才被轉發,不會轉發dog.puppy,也不會轉發dog.guard,只會轉發dog。
fanout:
?不處理路由鍵。你只需要簡單的將隊列綁定到交換機上。一個發送到交換機的消息都會被轉發到與該交換機綁定的所有隊列上。很像子網廣播,每臺子網內的主機都獲得了一份復制的消息。Fanout交換機轉發消息是最快的。
topic:
將路由鍵和某模式進行匹配。此時隊列需要綁定要一個模式上。符號“#”匹配一個或多個詞,符號“*”匹配不多不少一個詞。因此“audit.#”能夠匹配到“audit.irs.corporate”,但是“audit.*”?只會匹配到“audit.irs”。請參考下圖
虛擬主機
每一個RabbitMQ都能創建虛擬消息服務器,我們稱之為虛擬主機(vhost)。
每一個vhost本質上是一個mini版的RabbitMQ服務器,擁有自己的隊列、交換器、綁定。更重要的是他們擁有自己的權限機制。這使得你能夠安全的使用一個RabbitMQ服務器來服務于眾多應用。vhost之于RabbitMQ就像虛擬機之于物理服務器一樣。
用戶只能在虛擬主機的粒度進行權限控制。因此,如果需要禁止A組訪問B組的交換機/隊列/綁定,必須為A和B分別創建一個虛擬主機。每一個RabbitMQ服務器都有一個默認的虛擬主機“/”。默認的賬號密碼都為guest,為了安全起見,應該改掉。
注意:在RabbitMQ上創建vhost時,整個集群都會創建該vhost。
如何創建vhost?
| 1 | rabbitmqctl?add_vhost?[vhost_name] |
如何刪除vhost?
| 1 | rabbitmqctl?delete_vhost?[vhost_name] |
如何查看服務器上運行的vhost?
| 1 | rabbitmqctl?list_vhosts |
如何管理遠程的RabbitMQ節點?
| 1 | rabbitmqctl?-n?rabbit@server_name |
server_name可以是IP地址
持久化
默認情況下,當RabbitMQ服務器重啟后,那些隊列和交換器就都會消失。原因在于每個隊列和交換器的druable屬性。該屬性默認情況下為false,它決定了RabbitMQ是否需要在崩潰或者重啟后重新創建隊列。將它設置為true,就不需要再服務器重啟后重新創建隊列和交換器了。
如果你以為只需要將隊列和交換器的durable屬性設置為true,就可以讓消息幸免于重啟就錯了,能從AMQP中恢復崩潰的消息,我們稱之為持久化。在消息發布前,通過把它的“Delivery Mode”(投遞模式)設置為2,也就是持久的(persistent)即可。
注意:將投遞模式設置為2,僅僅表示消息被標識為持久化的,它還必須被發布到持久化的交換器,并投遞都持久化的隊列中才行。否則,包含持久化的隊列和交換器會在RabbitMQ重啟后小時,而消息變成孤兒。因此,實現持久化必須:
-
1.????將交換機設成?durable。
-
2.????將隊列設成?durable。
-
3.????將消息的?Delivery Mode?設置成2?
交換器和隊列可以設置為durable,那綁定(Bindings)怎么辦?我們無法在創建綁定的時候設置成durable。沒問題,如果你綁定了一個durable的隊列和一個durable的交換機,RabbitMQ會自動保留這個綁定。類似的,如果刪除了某個隊列或交換機(無論是不是durable),依賴它的綁定都會自動刪除。
注意兩點:
-
RabbitMQ?不允許你綁定一個非堅固(non-durable)的交換機和一個durable的隊列。反之亦然。要想成功必須隊列和交換機都是durable的。
-
一旦創建了隊列和交換機,就不能修改其標志了。例如,如果創建了一個non-durable的隊列,然后想把它改變成durable的,唯一的辦法就是刪除這個隊列然后重現創建。因此,最好仔細檢查創建的標志。
RabbitMQ持久化的機制
RabbitMQ能確保持久性消息能夠在服務器重啟后恢復的方式是,將消息寫入磁盤上的一個持久性的日志文件中。當發布一條持久性消息到持久化交換器上時,Rabbit會先將消息發送到持久化日志文件,然后再發送到持久化交換器。如果說這條消息路由到非持久化的隊列上,它會自動從持久性日志中移除,重啟后無法恢復。
性能
對于一個需要在重啟之后恢復的消息來說,它需要被寫入到磁盤上,這樣性能就會大打折扣。寫入磁盤要比寫入內存慢的不止一點點,而且會極大的減少RabbitMQ服務器每秒可以處理的消息數。另外,持久消息在RabbitMQ內建集群環境下工作得并不好。RabbitMQ集群的任何一個節點上都沒有備份的拷貝,這意味著運行某一隊列的集群節點崩潰了,在該節點恢復之前,這個隊列也就從集群隊列中消失了。
事務/confirm模式
RabbitMQ使用事務會降低大約2~10倍的消息吞吐量,幾乎吸干了RabbitMQ的性能。后來RabbitMQ團隊拿出了更好的加爵方案==>“發送方確認模式”(confirm)。需要將RabbitMQ信道設置為confirm模式,并且一旦設置成為confirm模式后,必須通過重新創建信道來關閉該設置。
confirm模式工作機制:
一旦信道進入confirm模式,所有信道上發布的消息都會被指派一個唯一的ID號(從1開始)。一旦消息被投遞給所有匹配的的隊列后,信道會發送一個發送方確認模式給生產者(包含消息的ID),這樣生產者就知道消息被安全送到目標隊列了。如果消息和隊列是可持久化的,那么確認消息只會在隊列將消息寫入磁盤后才會發出。發送方確認模式的最大好處是異步的。一旦發布了消息,生產者可以在等待確認的同時繼續發送下一條消息。當確認消息最終收到的時候,生產者應用程序的回調方法就會被觸發來處理該確認消息。如果RabbitMQ發生了內部錯誤從而導致消息丟失,Rabbit會發送一條nack(not acknowledge,未確認)消息。就像發送確認消息那樣,只不過這次明確說明消息已經丟失。由于沒有事務回滾的概念,因此發送方確認模式更加輕量級,同時,對RabbitMQ代理服務器的性能幾乎可以忽略不計。
本文轉自 曾哥最愛 51CTO博客,原文鏈接:http://blog.51cto.com/zengestudy/1874402,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的RabbitMQ基本概念的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ios开发两个简单的错误提示和原因
- 下一篇: 打造U盘版ESXi