RabbitMQ——消息服務概述、RabbitMQ的概述

目錄


一、消息服務概述

  1. 大多應用中,可通過消息服務中間件來提升系統異步通信、擴展解耦能力。

  2. 消息服務中兩個重要概念:
    消息代理(message broker)目的地(destination)
    當消息發送者發送消息以後,將由消息代理接管,消息代理保證消息傳遞到指定目的地。

  3. 消息隊列主要有兩種形式的目的地
    隊列(queue)點對點消息通信(point-to-point)
    主題(topic)發佈(publish)/訂閱(subscribe)消息通信

  4. 點對點式:
    – 消息發送者發送消息,消息代理將其放入一個隊列中,消息接收者從隊列中獲取消息內容,消息讀取後被移出隊列
    – 消息只有唯一的發送者和接受者,但並不是說只能有一個接收者

  5. 發佈訂閱式:
    – 發送者(發佈者)發送消息到主題,多個接收者(訂閱者)監聽(訂閱)這個主題,那麼就會在消息到達時同時收到消息

  6. JMS(Java Message Service)JAVA消息服務:
    – 基於JVM消息代理的規範。ActiveMQ、HornetMQ是JMS實現

  7. AMQP(Advanced Message Queuing Protocol)
    – 高級消息隊列協議,也是一個消息代理的規範,兼容JMS
    RabbitMQ是AMQP的實現

在這裏插入圖片描述

  1. Spring支持
    – spring-jms提供了對JMS的支持
    – spring-rabbit提供了對AMQP的支持
    – 需要ConnectionFactory的實現來連接消息代理
    – 提供JmsTemplate、RabbitTemplate來發送消息
    @JmsListener(JMS)、@RabbitListener(AMQP)註解在方法上監聽消息代理髮布的消息
    @EnableJms@EnableRabbit開啓支持

  2. Spring Boot自動配置
    – JmsAutoConfiguration
    RabbitAutoConfiguration

二、解決問題

跳轉到目錄

1、異步處理

場景說明:用戶註冊後,需要發註冊郵件和註冊短信,傳統的做法有兩種:a)串行的方式;b)並行的方式

串行方式:將註冊信息寫入數據庫後,發送註冊郵件,再發送註冊短信,以上三個任務全部完成後才返回給客戶端。 這有一個問題是:郵件,短信並不是必須的,它只是一個通知,而這種做法讓客戶端等待沒有必要等待的東西。
在這裏插入圖片描述
並行方式:將註冊信息寫入數據庫後,發送郵件的同時,發送短信,以上三個任務完成後,返回給客戶端,並行的方式能提高處理的時間。
在這裏插入圖片描述
假設三個業務節點分別使用50ms,串行方式使用時間150ms,並行使用時間100ms。雖然並性已經提高的處理時間,但是,前面說過,郵件和短信對我正常的使用網站沒有任何影響,客戶端沒有必要等着其發送完成才顯示註冊成功,應該是寫入數據庫後就返回。

消息隊列:引入消息隊列後,把發送郵件,短信不是必須的業務邏輯異步處理:
在這裏插入圖片描述
由此可以看出,引入消息隊列後,用戶的響應時間就等於寫入數據庫的時間+寫入消息隊列的時間(可以忽略不計),引入消息隊列後處理後,響應時間是串行的3倍,是並行的2倍。

2、應用解耦

場景:雙11是購物狂節,用戶下單後,訂單系統需要通知庫存系統,傳統的做法就是訂單系統調用庫存系統的接口。
在這裏插入圖片描述
這種做法有一個缺點:

  • 當庫存系統出現故障時,訂單就會失敗。
  • 訂單系統和庫存系統高耦合。

引入消息隊列:
在這裏插入圖片描述

  • 訂單系統:用戶下單後,訂單系統完成持久化處理,將消息寫入消息隊列,返回用戶訂單下單成功。

  • 庫存系統:訂閱下單的消息,獲取下單消息,進行庫操作。就算庫存系統出現故障,消息隊列也能保證消息的可靠投遞,不會導致消息丟失。

3、流量削鋒

流量削峯一般在秒殺活動中應用廣泛。

場景:秒殺活動,一般會因爲流量過大,導致應用掛掉,爲了解決這個問題,一般在應用前端加入消息隊列。

作用:

  • 可以控制活動人數,超過此一定閥值的訂單直接丟棄
  • 可以緩解短時間的高流量壓垮應用(應用程序按自己的最大處理能力獲取訂單)
    在這裏插入圖片描述
    用戶的請求,服務器收到之後,首先寫入消息隊列,加入消息隊列長度超過最大值,則直接拋棄用戶請求或跳轉到錯誤頁面。秒殺業務根據消息隊列中的請求信息,再做後續處理。

三、RabbitMQ概述

跳轉到目錄
MQ 全稱爲 Message Queue,是一種分佈式應用程序的的通信方法,是``消費者-生產者模型的典型的代表,producer 往消息隊列中不斷寫入消息,而另一端 consumer 則可以讀取或者訂閱隊列中的消息,這點可以與數據結構中隊列的作用相類似,具有 FIFO 的特點。

RabbitMQ 是 MQ 產品的典型實現,是基於 AMQP 協議可複用的企業消息系統。業務上,可以實現服務提供者和消費者之間的數據解耦,提供高可用性的消息傳輸機制,在實際生產中應用相當廣泛。

1、消息隊列

首先來一張消息隊列的經典圖,可以劃分爲三個角色: Producer, Queue, Consumer
在這裏插入圖片描述

  • Queue:爲承載消息的容器,爲什麼是隊列而不是棧呢?主要是因爲絕大部分的場景,我們都是希望消息是先進先出,有順序的
  • Producer:生產者,就是產生消息,並不斷往隊列塞的角色
  • Consumer:消費者,也就是不斷從隊列中獲取消息的角色

2、理解消息隊列

其實在生活中,這種模型用得非常多,就比如我們都會接觸的網購快遞,可以說是一個典型的消息隊列的 例子了:

商家不斷的把商品扔給快遞公司(注意不是直接將商品給買家),而快遞公司則將商品根據地質分發對應的買家

對上面這個過程進行拆解,可以映射扮演的角色

  • 商品:Message,傳遞的消息,由商家投遞給快遞公司時,需要進行打包(一般Producer生產消息也會將實體數據進行封裝)
  • 商家:Produer 生產者
  • 快遞公司: Queue,消息的載體
  • 買家:Consumer 消費者

那麼快遞公司時怎麼知道要把商品給對應的買家呢?根據包裹上的地址+電話

  • 同樣消息隊列也需要一個映射規則,實現Message和Consumer之間的路由

3、RabbitMQ的基本概念

在這裏插入圖片描述

核心概念:
  • Message:消息,包含消息頭(即附屬的配置信息)和消息體(即消息的實體內容)消息,消息體是不透明的,消息體是由一些可選屬性組成的,包括路由鍵(routing-key)、優先級(priority)、持久性存儲(delivery-mode)等。

    • Exchange(交換機)就是通過路由鍵來將消息路由到哪個消息隊列中;
  • Publisher:消息生產者,向交換機發布消息的客戶端程序,我們可以簡單理解爲就是一個 Java 程序。

  • Exchange:交換機,用來接收生產者發送的消息並將這些消息路由給服務器中的消息隊列

    常見的三種交換器類型:
    direct:發佈與訂閱,完全匹配 。我們可以簡單理解爲一對一的關係,一個交換器將消息發送給一個隊列,是完全匹配的
    fanout:廣播,所有訂閱該廣播的隊列都可以收到該消息。廣播式交換器,不管消息的 ROUTING_KEY 設置爲什麼,Exchange 都會將消息轉發給所有綁定的 Queue
    topic:主題,規則匹配 。

  • Queue:消息隊列,用來保存消息直到發送給消費者。它是消息的容器,也是消息的終點。一個消息可投入一個或多個隊列。消息一直在隊列裏面,等待消費者連接到這個隊列將其取走。

  • Binding:綁定,用於給 Exchange(交換機) 和 Queue(消息隊列) 建立關係,把 exchange 和 queue 按照路由規則綁定起來, 可以是多對多的關係。

  • Connection:網絡連接

  • Channel:信道,MQ(消息隊列)與外部打交道都是通過Channel來的,發佈消息、訂閱隊列還是接收消息,這些動作都是通過Channel完成;簡單來說就是消息通過Channel塞進隊列或者流出隊列。在客戶端的每個連接裏,可建立多個channel。因爲對於操作系統來說建立和銷燬 TCP 都是非常昂貴的開銷,所以引入了信道的概念,以複用一條 TCP 連接。

  • Consumer:消費者,從消息隊列中獲取消息的客戶端應用程序。

  • Virtual Host:虛擬主機,表示一批交換器、消息隊列和相關對象。虛擬主機是共享相同的身份認證和加密環境的獨立服務器域。每個 vhost 本質上就是一個 mini 版的 RabbitMQ 服務器,擁有自己的隊列、交換器、綁定和權限機制。vhost 是 AMQP 概念的基礎,必須在連接時指定,RabbitMQ 默認的 vhost 是/一個 broker 裏可以有多個 vhost,用作不同用戶的權限分離。

  • Broker:消息隊列服務器實體,它提供一種傳輸服務,它的角色就是維護一條從生產者到消費者的路線,保證數據能按照指定的方式進行傳輸。可以理解爲在 Linux 上創建的虛擬機實體。

4、通信過程

  1. 生產者(Publisher)生產消息, 消息通過Channel(信道)發送給Broker(服務器主體), Broker再分配給一個Exchange(交換機)
  2. Exchange收到消息後, 通過消息中的ROUTEKEY(路由鍵), 將消息轉發給匹配的Queue(消息隊列)
  3. Queue收到消息後, 將消息通過Channel發送給消費者(Consumer)
  4. Consumer收到消息後, 發送ACK(確認標誌)給消息隊列確認收到消息
  5. Queue收到ACK, 刪除該消息隊列中緩存的此條消息.

四、RabbitMQ運行機制

跳轉到目錄
AMQP 中的消息路由

  • AMQP 中消息的路由過程和 Java 開發者熟悉的 JMS 存在一些差別,AMQP 中增加了 ExchangeBinding 的角色。生產者把消息發佈到 Exchange 上,消息最終到達隊列並被消費者接收,而 Binding 決定交換器的消息應該發送到那個隊列。
    在這裏插入圖片描述
Exchange類型

Exchange分發消息時根據類型的不同分發策略有區別,目前共四種類型:directfanouttopicheaders 。headers 匹配 AMQP 消息的 header 而不是路由鍵, headers 交換器和 direct 交換器完全一致,但性能差很多,目前幾乎用不到了,所以直接看另外三種類型:

在這裏插入圖片描述
消息中的路由鍵(routing key)如果和 Binding 中的binding key 一致, 交換器就將消息發到對應的隊列中。路由鍵與隊列名完全匹配,如果一個隊列綁定到交換機要求路由鍵爲“dog”,則只轉發 routing key 標記爲“dog”的消息,不會轉發“dog.puppy”,也不會轉發“dog.guard”等等。它是完全匹配、單播的模式。

在這裏插入圖片描述
每個發到 fanout 類型交換器的消息都會分到所有綁定的隊列上去。fanout 交換器不處理路由鍵,只是簡單的將隊列綁定到交換器上,每個發送到交換器的消息都會被轉發到與該交換器綁定的所有隊列上。很像子網廣播,每臺子網內的主機都獲得了一份複製的消息。fanout 類型轉發消息是最快的。

在這裏插入圖片描述
topic 交換器通過模式匹配分配消息的路由鍵屬性,將路由鍵和某個模式進行匹配,此時隊列需要綁定到一個模式上。它將路由鍵和綁定鍵的字符串切分成單詞,這些單詞之間用點隔開。它同樣也會識別兩個通配符:符號“#”和符號“*”。#匹配0個或多個單詞,*匹配一個單詞。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章