javascript
Spring Boot与消息
首先我們結合3個例子來說說消息在實際中的應用,以建立起消息的概念:
1.異步處理:
用戶在注冊的時候,我們需要給用戶發送注冊郵件和注冊短信,如果使用串行處理,就會耗費比較長的時間,如果我們使用異步處理的話,就可以節約一些時間,如果使用消息隊列,又可以進一步減少這些時間。
2.應用解耦:
這個比較好理解,比如不同的系統之間使用消息隊列來解耦合,這樣就可以不用調用對方接口,減少耦合關系。
3.流量削峰:
比如我們有一個秒殺的業務,如果每個用戶在秒殺的時候直接和系統打交道,這么大的用戶量,可能會導致系統卡死。這個時候我們可以使用消息隊列,比如只有100個商品,那么就把消息隊列大小設置為100,用戶請求直接放到消息隊列中,如果消息隊列滿了,我們就返回用戶秒殺失敗的信息,之后秒殺業務再從消息隊列中慢慢取數據處理。
消息服務中兩個重要概念:消息代理(message broker)和目的地(destination),當消息發送者發送消息以后,將由消息代理接管,消息代理保證消息傳遞到指定目的地。消息隊列主要有兩種形式的目的地:
消息代理規范有兩種:
- JMS(Java Message Service)JAVA消息服務:基于JVM消息代理的規范。ActiveMQ、HornetMQ是JMS實現。
- AMQP(Advanced Message Queuing Protocol),高級消息隊列協議,也是一個消息代理的規范,兼容JMS,RabbitMQ是AMQP的實現
兩者具體差別如下:
Spring Boot對兩種實現標準都做了支持,只需要導入相關的starter即可,如spring-boot-starter-amqp。
RabbitMQ簡介:
RabbitMQ是一個由erlang開發的AMQP(Advanved Message Queue Protocol)的開源實現。
核心概念
-
Message
消息,消息是不具名的,它由消息頭和消息體組成。消息體是不透明的,而消息頭則由一系列的可選屬性組成,這些屬性包括routing-key(路由鍵)、priority(相對于其他消息的優先權)、delivery-mode(指出該消息可能需要持久性存儲)等。 -
Publisher
消息的生產者,也是一個向交換器發布消息的客戶端應用程序。 -
Exchange
交換器,用來接收生產者發送的消息并將這些消息路由給服務器中的隊列。 -
Queue
消息隊列,用來保存消息直到發送給消費者。它是消息的容器,也是消息的終點。一個消息可投入一個或多個隊列。消息一直在隊列里面,等待消費者連接到這個隊列將其取走。 -
Binding
綁定,用于消息隊列和交換器之間的關聯。一個綁定就是基于路由鍵將交換器和消息隊列連接起來的路由規則,所以可以將交換器理解成一個由綁定構成的路由表。Exchange 和Queue的綁定可以是多對多的關系。 -
Connection
網絡連接,比如一個TCP連接。 -
Channel
信道,多路復用連接中的一條獨立的雙向數據流通道。信道是建立在真實的TCP連接內的虛擬連接,AMQP 命令都是通過信道發出去的,不管是發布消息、訂閱隊列還是接收消息,這些動作都是通過信道完成。因為對于操作系統來說建立和銷毀TCP 都是非常昂貴的開銷,所以引入了信道的概念,以復用一條TCP 連接。 -
Consumer
消息的消費者,表示一個從消息隊列中取得消息的客戶端應用程序。 -
Virtual Host
虛擬主機,表示一批交換器、消息隊列和相關對象。虛擬主機是共享相同的身份認證和加密環境的獨立服務器域。每個vhost 本質上就是一個mini 版的RabbitMQ 服務器,擁有自己的隊列、交換器、綁定和權限機制。vhost 是AMQP 概念的基礎,必須在連接時指定,RabbitMQ 默認的vhost 是/ 。 -
Broker
表示消息隊列服務器實體
他們之間的關系如下所示:
RabbitMQ運行機制如下:
AMQP 中消息的路由過程和Java 開發者熟悉的JMS 存在一些差別,AMQP 中增加了Exchange和Binding的角色。生產者把消息發布到Exchange 上,消息最終到達隊列并被消費者接收,而Binding 決定交換器的消息應該發送到那個隊列。
Exchange分發消息時根據類型的不同分發策略有區別,目前共四種類型:direct、fanout、topic、headers 。headers 匹配AMQP 消息的header 而不是路由鍵,headers 交換器和direct 交換器完全一致,但性能差很多,目前幾乎用不到了,所以直接看另外三種類型:
- direct類型:
消息中的路由鍵(routing key)如果和Binding 中的binding key 一致,交換器就將消息發到對應的隊列中。路由鍵與隊列名完全匹配,如果一個隊列綁定到交換機要求路由鍵為“dog”,則只轉發routing key 標記為“dog”的消息,不會轉發“dog.puppy”,也不會轉發“dog.guard”等等。它是完全匹配、單播的模式。
- fanout類型:
每個發到fanout 類型交換器的消息都會分到所有綁定的隊列上去。fanout 交換器不處理路由鍵,只是簡單的將隊列綁定到交換器上,每個發送到交換器的消息都會被轉發到與該交換器綁定的所有隊列上。很像子網廣播,每臺子網內的主機都獲得了一份復制的消息。fanout 類型轉發消息是最快的。
- topic類型:
topic 交換器通過模式匹配分配消息的路由鍵屬性,將路由鍵和某個模式進行匹配,此時隊列需要綁定到一個模式上。它將路由鍵和綁定鍵的字符串切分成單詞,這些單詞之間用點隔開。它同樣也會識別兩個通配符:符號“#”和符號“*”。#匹配0個或多個單詞,*匹配一個單詞。類似有選擇的廣播。
接下來我們在Spring Boot工程中使用rabbitmq,首先你需要拉取docker鏡像,并運行這個鏡像。
之后在工程中引入amqp:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency>IDEA中使用Ctrl+N查找到RabbitAutoConfiguration類,可以看到它是使用RabbitProperties來封裝了RabbitMQ配置,如果需要自己配置,我們直接在配置文件中寫spring.rabbitmq.xxx即可,如:
spring.rabbitmq.host=192.168.0.1 spring.rabbitmq.username=guest spring.rabbitmq.password=guest此外RabbitAutoConfiguration類還給我們注冊了RabbitTemplate來方便我們發送和接收消息。使用的時候自動注入即可。更多的關于rabbitmq的操作,可以查看相關資料,這里就不一一講解了。
總結
以上是生活随笔為你收集整理的Spring Boot与消息的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Boot使用缓存功能
- 下一篇: 从源码理解ReentrantLock