RabbitMQ 入門之基礎概念

什麼是消息隊列(MQ)

消息是在不一樣應用間傳遞的數據。這裏的消息能夠很是簡單,好比只包含字符串,也能夠很是複雜,包含多個嵌套的對象。消息隊列(Message Queue)簡單來講就是一種應用程序間的通信方式,消息發送後當即返回,而後由消息系統保證消息的可靠性傳輸,消息生產者只須要把消息發到 MQ 中就能夠了,不須要關心消息的消費,一樣,消息消費者只管從 MQ 中拉取消息而不論是誰生產的消息,經過這樣的一個「互相不知道對象存在」模式,將消息的生產者和消息的消費者解耦了。瀏覽器

什麼場景下考慮使用消息隊列

從上面能夠知道,消息隊列是一種應用間的異步協做機制,那麼咱們何時須要用到 MQ 呢?以常見的訂單系統爲例,當用戶點擊「下單」後的業務邏輯可能包括:扣減庫存、生成相應訂單數據、發短信通知等。在項目和業務發展初期上面這些邏輯可能放在一塊兒執行,隨着業務的發展訂單量的增長,須要提高系統服務的性能,此時就能夠將一些不須要當即生效的操做拆分出來異步執行,好比發送短信通知等。這種場景下就可使用 MQ ,在下單主流程(好比扣減庫存、生成訂單數據等)完成以後發送一條消息到 MQ 讓主流程快速走完,而後由另一個線程拉取 MQ 的消息,執行相應的業務邏輯。這裏的例子主要是用消息隊列來解耦。bash

RabbitMQ 的特色

RabbitMQ 是一個由 Relang 語言開發的 AMQP 的開源實現。AMQP(Advanced Message Queue:高級消息隊列協議)它是應用層協議的一個開放標準,爲面向消息的中間件設計,基於此協議的客戶端與消息中間件可傳遞消息,並不受產品、開發語言等條件的限制。RabbitMQ 最初起源於消息系統,用於在分佈式系統中存儲轉發消息,具體有以下一些特色:服務器

  • 可靠性: RabbitMQ 使用一些機制來保證可靠性,好比持久化、傳輸確認機制(ack)和發佈確認等。
  • 靈活的路由策略: 在消息進入隊列以前,經過 Exchange 來路由消息,對於典型的路由功能,RabbitMQ 已經提供了一些內置的 Exchange 來實現。針對複雜的路由功能,能夠將多個 Exchange 綁在一塊兒,也經過插件機制實現本身的 Exchange。
  • 消息集羣: 多個 RabbitMQ 服務器能夠組成一個集羣,造成一個邏輯 Broker。
  • 高可用: 隊列能夠在集羣中的集羣上進行鏡像,使得在部分節點出問題的狀況下隊列仍然可用。
  • 多種協議: RabbitMQ 支持多種消息隊列協議,好比 STOMP、MQTT 等。
  • 多語言客戶端: RabbitMQ 幾乎支持多有經常使用的語言,好比:Java、.NET 等
  • 管理界面: RabbitMQ 提供了一個易用的用戶界面,使得用戶能夠監控和管理消息 Broker 的許多方面。

RabbitMQ 安裝(mac)和運行

一、安裝
由於 RabbitMQ 依賴於 Erlang 語言,因此在安裝 RabbitMQ 以前須要先安裝 Erlang 環境,可是因爲是 Mac 環境,可使用 HomeBrew 安裝,安裝前先更新 brew:網絡

brew update

接着安裝 RabbitMQ 便可,安裝過程當中會自動安裝其所依賴的 Erlang。運維

rabbitmq-base-7.jpeg

二、運行
RabbitMQ 的啓動運行很簡單,找到其安裝目錄後(使用 Homwbrew 安裝的默認目錄爲:/usr/local/Cellar/rabbitmq),進入到目錄的 sbin 目錄下,能夠看到有 6 個
以 rabbitmq 開頭的可執行文件,直接執行 rabbitmq-server 便可。異步

rabbitmq-base-8.jpeg

啓動正常的話能夠看到啓動過程的日誌信息和最後的 completed with 6 plugins,這也說明啓動的時候默認加載了 6 個插件。分佈式

rabbitmq-base-9.jpeg

此時經過瀏覽器訪問 http://localhost:15672 能夠看到其管理界面(默認用戶名和密碼都是 guest),能夠在 admin 選項卡頁面新增用戶,管理界面以下:性能

rabbitmq-base-10.jpeg

PS: 以上方式不是後臺啓動,若是想讓 RabbitMQ 後臺守護進程的方式啓動的話,能夠在啓動的時候加上 -detached 參數。加密

rabbitmq-base-11.jpeg

三、查詢服務器狀態
在安裝目錄的 sbin 下面有個可執行文件 rabbitmqctl ,它提供了 RabbitMQ 管理須要的幾乎一站式解決方案,絕大部分的運維命令它均可以提供。查詢 RabbitMQ 服務器的狀態信息能夠用參數 status。操作系統

rabbitmq-base-12.jpeg

RabbitMQ 中的基礎概念

一、消息模型 幾乎全部的 MQ 抽象來講都是同樣的過程:消費者訂閱某個隊列,生產者生產消息,而後發佈到隊列中,最後將消息發送到監聽該隊列的消費者那裏。以下圖所示:

rabbitmq-base-1.jpeg

二、基本概念 上面上一個消息隊列的抽象概述,具體到 RabbitMQ 有一些特有的概念,RabbitMQ 是 AMQP 協議的一個開源實現,其內部概念大都是 AMQP 協議的一些概念。

rabbitmq-base-2.jpeg

名稱 描述
Message 消息 消息是不具名的,它由消息頭和消息體組成。消息體是不透明的,而消息頭則是由一系列的可選屬性組成,這些屬性包括 routing-key(路由鍵)、priority(相對於其它消息的優先權)、delivery-mode(指出該消息可能須要持久性存儲)等。
Publisher 消息生產者 一個向交換機發送消息的客戶端應用程序。
Exchange 交換器 用來接收生產者發送過來的消息,並將這些消息發送給服務器中的隊列。
Binding 綁定 用於消息隊列和交換器之間的關聯,一個綁定就是一個基於路由鍵將交換器和消息隊列鏈接起來的路由規則,因此能夠將交換器理解成一個由綁定構成的路由表。
Queue 消息隊列 用來保存消息直到發送給消費者,它是消息的容器,也是消息的終點,一個消息可投入一個或多個隊列,消息一直在隊列裏面,等待消費者鏈接到這個隊列並將其取走。
Connection 網絡鏈接 好比一個 TCP 鏈接。
Channel 信道 多路複用鏈接中的一條獨立雙向數據流通道,信道是創建在真實 TCP 鏈接內的虛擬鏈接,AMQP 命令都是經過信道發送出去的,不論是發佈消息、訂閱消息仍是接收消息,這些動做都是經過信道完成的。由於對於操做系統來講創建和銷燬 TCP 都是很是昂貴的開銷,因此引入了信道的概念,以複用一條 TCP 鏈接。
Consumer 消息的消費者 一個從消息隊列中獲取消息的客戶端應用程序。
Virtual Host 虛擬主機 表示一批交換器、消息隊列和相關對象。虛擬主機是共享相同身份認證和加密環境的對服務器域。每一個 vhost 本質上是一個 mini 版的 RabbitMQ 服務器,擁有本身的隊列、交換器、綁定和權限機制。vhost 是 AMQP 概念的基礎,必須在鏈接時指定,RabbitMQ 默認的 vhost 是 / 。

三、AMQP 中的消息路由 AMQP 中消息路由過程和 Java 開發者熟悉的 JMS 存在一些差異,AMQP 中增長了 Exchange 和 Binding 的角色。生產者把消息發送到 Exchange 上,消息最終到達隊列並被消費者接收,而 Binding 決定交換器的消息應該發到哪一個隊列。

rabbitmq-base-3.jpeg

四、Exchange 類型 Exchange 分發消息時根據類型的不一樣分發策略略有區別,目前共有四種類型:direct、fanout、topic、headers。headers 匹配 AMQP 消息的 header 而不是路由鍵,此外 headers 交換器和 direct 交換器徹底一致,但性能差不少,目前幾乎用不到了,因此直接看另外三種類型便可。

4.一、direct 類型

rabbitmq-base-4.jpeg

消息中的路由鍵(routing key)若是和 Binding 中的 binding key 一致,交換器就將消息發到對應的隊列中。路由鍵與隊列名徹底匹配,若是一個隊列綁定到交換機要求路由鍵爲 "dog",則只轉發 routing key 標記爲 「dog」 的消息,不會轉發 "dog.puppy",也不會轉發 "dog.guard" 等等。它是徹底匹配、單播的模式。

4.二、fanout 類型

rabbitmq-base-5.jpeg

每一個發到 fanout 類型交換機的消息都會發到全部綁定的隊列上去。fanout 交換器不處理路由鍵,只是簡單的將隊列綁定到交換器上,每一個發送到交換器的消息都會被轉發到與該交換器綁定的全部隊列上。很像子網廣播,每臺子網內的主機都得到一份複製的消息。fanout 類型轉發消息是最快的。

三、topic 類型

rabbitmq-base-6.jpeg

topic 交換器經過模式匹配分配消息的路由鍵屬性,將路由鍵和某個模式進行匹配,此時隊列須要綁定到一個模式上,它將路由鍵和綁定的字符串切分紅單詞,這些單詞之間用點隔開。它一樣也識別兩個通配符:符號 "#" 和符號 ""。# 符號匹配 0 個或多個單詞, 符號匹配很少很多一個單詞。

總結

本文主要講了關於 RabbitMQ 的安裝以及基礎概念的相關介紹,因爲它是基於 Erlang 語言開發,可能對於部分 Java 開發者想了解其底層實現細節以及排查比較複雜的問題時不是很友好。

相關文章
相關標籤/搜索