是應用層協定的一個開放标準,為面向消息的中間件設計。基于此協定的用戶端與消息中間件可傳遞消息,并不受用戶端/中間件不同産品,不同的開發語言等條件的限制。目标是實作一種在全行業廣泛使用的标準消息中間件技術,以便降低企業和系統內建的開銷,并且向大衆提供工業級的內建服務。
主要實作有 RabbitMQ。
首先作為用戶端(無論是生産者還是消費者),你如果要與 RabbitMQ 通訊的話,你們之間必須建立一條 TCP 連接配接,當然同時建立連接配接後,用戶端還必須發送一條“問候語”讓彼此知道我們都是符合 AMQP 的語言的,比如你跟别人打招呼一般會說“你好!”,你跟國外的美女一般會說“hello!”一樣。
你們确認好“語言”之後,就相當于用戶端和 RabbitMQ 通過“認證”了。你們之間可以建立一條 AMQP 的信道。
概念:信道是生産者/消費者與 RabbitMQ 通信的管道。信道是建立在 TCP 連接配接上的虛拟連接配接,什麼意思呢?就是說 rabbitmq 在一條 TCP 上建立成百上千個信道來達到多個線程處理,這個 TCP 被多個線程共享,每個線程對應一個信道,信道在 RabbitMQ 都有唯一的 ID ,保證了信道私有性,對應上唯一的線程使用。
疑問:為什麼不建立多個 TCP 連接配接呢?原因是 rabbit 保證性能,系統為每個線程開辟一個 TCP 是非常消耗性能,每秒成百上千的建立銷毀 TCP 會嚴重消耗系統。是以 rabbitmq 選擇建立多個信道(建立在 tcp 的虛拟連接配接)連接配接到 rabbit 上。
從技術上講,這被稱之為“多路複用”,對于執行多個任務的多線程或者異步應用程式來說,它非常有用。
生産者:消息的建立者,發送到 rabbitmq;
消費者:連接配接到 rabbitmq,訂閱到隊列上,消費消息,持續訂閱(basicConsumer)和單條訂閱(basicGet).
消息:包含有效載荷和标簽,有效載荷指要傳輸的資料,,标簽描述了有效載荷,并且 rabbitmq 用它來決定誰獲得消息,消費者隻能拿到有效載荷,并不知道生産者是誰。
隊列通過路由鍵(routing key,某種确定的規則)綁定到交換器,生産者将消息釋出到交換器,交換器根據綁定的路由鍵将消息路由到特定隊列,然後由訂閱這個隊列的消費者進行接收。
(routing_key 和 綁定鍵 binding_key 的最大長度是 255 個位元組)
消費者收到的每一條消息都必須進行确認(自動确認和自行确認)。
消費者在聲明隊列時,可以指定 autoAck 參數,當 autoAck=false 時,RabbitMQ 會等待消費者顯式發回 ack信号後才從記憶體(和磁盤,如果是持久化消息的話)中移去消息。否則,RabbitMQ 會在隊列中消息被消費後立即删除它。
采用消息确認機制後,隻要令 autoAck=false,消費者就有足夠的時間處理消息(任務),不用擔心處理消息過程中消費者程序挂掉後消息丢失的問題,因為 RabbitMQ 會一直持有消息直到消費者顯式調用 basicAck 為止。
當 autoAck=false 時,對于 RabbitMQ 伺服器端而言,隊列中的消息分成了兩部分:一部分是等待投遞給消費者的消息;一部分是已經投遞給消費者,但是還沒有收到消費者 ack信号的消息。如果伺服器端一直沒有收到消費者的 ack信号,并且消費此消息的消費者已經斷開連接配接,則伺服器端會安排該消息重新進入隊列,等待投遞給下一個消費者(也可能還是原來的那個消費者)。
RabbitMQ 不會為未 ack 的消息設定逾時時間,它判斷此消息是否需要重新投遞給消費者的唯一依據是消費該消息的消費者連接配接是否已經斷開。這麼設計的原因是 RabbitMQ 允許消費者消費一條消息的時間可以很久很久。
如果消息達到無人訂閱的隊列會怎麼辦?消息會一直在隊列中等待,RabbitMq 預設隊列是無限長度的。
多個消費者訂閱到同一隊列怎麼辦?消息以循環的方式發送給消費者,每個消息隻會發送給一個消費者。
消息路由到了不存在的隊列怎麼辦?一般情況下,涼拌,RabbitMq 會忽略,當這個消息不存在,也就是這消息丢了。
虛拟消息伺服器,vhost,本質上就是一個 mini 版的 mq伺服器,有自己的隊列、交換器和綁定,最重要的,自己的權限機制。Vhost 提供了邏輯上的分離,可以将衆多用戶端進行區分,又可以避免隊列和交換器的命名沖突。Vhost 必須在連接配接時指定,rabbitmq 包含預設 vhost:“/”,通過預設使用者和密碼 guest 進行通路。
rabbitmq 裡建立使用者,必須要被指派給至少一個 vhost,并且隻能通路被指派内的隊列、交換器和綁定。Vhost 必須通過 rabbitmq 的管理控制工具建立。

共有四種 direct,fanout,topic,headers,其種 headers(幾乎和 direct 一樣)不實用,可以忽略。
路由鍵完全比對,消息被投遞到對應的隊列, direct 交換器是預設交換器。聲明一個隊列時,會自動綁定到預設交換器,并且以隊列名稱作為路由鍵:channel->basic_public($msg,’’,’queue-name’)
消息廣播到綁定的隊列,不管隊列綁定了什麼路由鍵,消息經過交換器,每個隊列都有一份。
通過使用“*”和“#”通配符進行處理,使來自不同源頭的消息到達同一個隊列,”.”将路由鍵分為了幾個辨別符,“*”比對 1 個,“#”比對一個或多個。