spring-boot-route(十三)整合RabbitMQ
阿新 • • 發佈:2020-10-12
這篇是SpringBoot整合訊息佇列的第一篇文章,我們詳細介紹下訊息佇列的相關內容。
## 訊息佇列簡介
### 1. 什麼是訊息佇列
`MQ`(Message Quene):通過典型的生產者和消費者模型,生產者不斷向訊息佇列中產生訊息,消費者不斷的從佇列中獲取訊息。因為生產者和消費者都是非同步的,而且生產者只關心訊息的傳送,消費者只關心訊息的接收,沒有業務邏輯的侵入,輕鬆實現業務解耦。
### 2. 訊息佇列有什麼用
- 非同步處理
場景描述:某商場具有註冊功能,註冊的時候需要傳送簡訊驗證碼。
傳統的做法是使用者提交資訊到使用者服務,使用者服務呼叫簡訊服務傳送簡訊,然後給使用者返回響應,這種是同步的處理方式,耗時較長。加入訊息佇列後,使用者直接提交資訊到使用者服務,將資訊寫入訊息佇列,直接給使用者返回響應,簡訊服務從訊息佇列中讀取訊息進行傳送簡訊。
- 應用解耦
場景描述:某商場下單流程。
傳統做法是使用者下單,訂單系統去查詢庫存系統,如果庫存系統宕機了,則下單失敗,損失訂單量。加入訊息佇列後,使用者下單,訂單系統記錄訂單,將訂單資訊寫入訊息佇列,下單成功,然後庫存系統恢復正常後去操作資料庫庫存(不考慮庫存為0的情況)。這樣訂單系統和庫存系統就達到鬆耦合的目的了
- 流量削峰
場景描述:秒殺活動。
流量過大肯定會導致響應超時或系統宕機,加入訊息佇列,使用者秒殺請求寫入訊息佇列,設定訊息佇列的長度等屬性,達到訊息佇列最大長度後,直接返回秒殺失敗,然後再去消費訊息佇列的資料,完成秒殺。
## RabbitMQ簡介
RabbitMQ是用Erlang語言編寫的,實現了高階訊息佇列協議(AMQP)的訊息中介軟體。
### 1. AMQP協議概念
`AMQP`:`AMQP`是一種連結協議,直接定義網路交換的資料格式,這使得實現了`AMQP`的`provider`本身就是跨平臺的。以下是`AMQP`協議模型:
![](https://img2020.cnblogs.com/blog/1719198/202010/1719198-20201012103511494-1448943685.png)
- server - 又稱broker,接收客戶端的連結,實現amqp實體服務。
- Connection - 連結,應用程式跟broker的網路連結。
- channel - 網路通道,幾乎所有的操作都是在channel中進行,資料的流轉都要在channel上進行。channel是進行訊息讀寫的通道。客戶端可以建立多個channel,每個channel代表一個會話任務。
- message - 訊息,伺服器與應用程式之間傳送的資料。由properties和body組成。properties可以對訊息進行修飾,比如訊息的升級,延遲等高階特性。body就是訊息體的內容。
- virtual host - 虛擬主機,用於進行邏輯隔離,最上層的訊息路由,一個虛擬地址裡面可以有多個交換機。exchange和訊息佇列message quene。
- exchange - 交換機,接收訊息,根據路由器轉發訊息到繫結的佇列。
- binding - 繫結,交換機和佇列之間的虛擬連結,繫結中可以包含routing key。
- routing key - 一個路由規則,虛擬機器可以用它來確定jiekyi如何路由一個特定訊息。
- quene - 訊息佇列,儲存訊息並將它們轉發給消費者。
### 2. RabbitMQ的訊息模型
#### 1. 簡單模型
![img](https://www.rabbitmq.com/img/tutorials/python-one.png)
在上圖中:
- p:生成者
- C:消費者
- 紅色部分:quene,訊息佇列
#### 2. 工作模型
![img](https://www.rabbitmq.com/img/tutorials/python-two.png)
在上圖中:
- p:生成者
- C1、C2:消費者
- 紅色部分:quene,訊息佇列
當訊息處理比較耗時時,就會出現生產訊息的速度遠遠大於消費訊息的速度,這樣就會出現訊息堆積,無法及時處理。這時就可以讓**多個消費者繫結一個佇列,去消費訊息**,佇列中的訊息一旦消費就會丟失,因此任務不會重複執行。
#### 3. 廣播模型(fanout)
![img](https://www.rabbitmq.com/img/tutorials/python-three.png)
這種模型中生產者傳送的訊息所有消費者都可以消費。
在上圖中:
- p:生成者
- X:交換機
- C1、C2:消費者
- 紅色部分:quene,訊息佇列
#### 4. 路由模型(routing)
![python-four.png (423×171)](https://www.rabbitmq.com/img/tutorials/python-four.png)
這種模型消費者傳送的訊息,不同型別的訊息可以由不同的消費者去消費。
在上圖中:
- p:生成者
- X:交換機,接收到生產者的訊息後將訊息投遞給與routing key完全匹配的佇列
- C1、C2:消費者
- 紅色部分:quene,訊息佇列
#### 5. 訂閱模型(topic)
![img](https://www.rabbitmq.com/img/tutorials/python-five.png)
這種模型和direct模型一樣,都是可以根據routing key將訊息路由到不同的佇列,只不過這種模型可以讓佇列繫結routing key 的時候使用萬用字元。這種型別的routing key都是由一個或多個單片語成,多個單詞之間用`.`分割。
萬用字元介紹:
**`*`:只匹配一個單詞**
**`#`:匹配一個或多個單詞**
#### 6. RPC模型
![img](https://www.rabbitmq.com/img/tutorials/python-six.png)
這種模式需要通知遠端計算機執行功能並等待返回執行結果。這個過程是阻塞的。
當客戶端啟動時,它建立一個匿名獨佔回撥佇列。並提供名字為call的函式,這個call會發送RPC請求並且阻塞直到收到RPC運算的結果。
## Spring Boot整合RabbitMQ
第一步:引入pom依賴
```xml
```
第二步:增加RabbitMQ服務配置資訊
```yml
spring:
rabbitmq:
virtual-host: javatrip
port: 5672
host: 127.0.0.1
username: guest
password: guest
```
這裡我們用廣播模型來舉例使用,廣播模型(fanout)比較好理解,就像公眾號一樣,我每天推文章後,會推送給每個關注使用者,他們都可以看到這條訊息。
廣播模型注意點:
1. 可以有多個佇列
2. 每個佇列都需要繫結交換機
3. 每個消費者有自己的佇列
4. 交換機把訊息傳送給繫結過的所有佇列
### 1. 定義兩個佇列
```java
@Configuration
public class RabbitConfig {
final static String queueNameA = "first-queue";
final static String queueNameB = "second-queue";
/***
* 定義一個佇列,設定佇列屬性
* @return
*/
@Bean("queueA")
public Queue queueA(){