javascript
SpringCloud 微服务 (十) 消息队列MQ 基础
2019獨角獸企業重金招聘Python工程師標準>>>
壹
之前學習了SpringCloud Bus結合MQ,沒有多學習MQ,本次學習相關內容,先了解異步,同步就不說了
?
異步: 客戶端非阻塞進程,服務端響應可以是非即時的
應用場景:?
①通知類的服務->發出去即可,無需回應;?
②請求的異步響應->就是客戶端發送請求,服務端異步響應請求,客戶端不會產生阻塞且是默認響應,但不會立刻送達;
①②都屬于1對1交互模式;
③消息->可以實現1對多的交互模式,比如發布訂閱模式下,客戶端發布消息通知,可以被0到N個服務消費,再例如客戶端發送消息等待其他服務的響應
?
MQ在分布式系統中都會用到的組件,還是很重要的
應用場景:?
①異步處理->比如用戶注冊的時候,需要手機(郵箱)驗證,有的平臺用戶注冊還可以加用戶積分(經驗)獎勵,還有什么身份證認證等等很多,這時候在用戶信息寫入數據庫后,可以通過異步消息讓驗證服務或者獎勵各自執行各自的服務,提升效率,提升用戶體驗;
②流量控制->比如電商秒殺活動,秒殺時一般會因為流量突然暴漲,過大流量導致服務掛掉,解決此問題,一般會在服務前端加入消息隊列,控制可容流量,如果消息隊列長度超過最大可容數量,需要丟棄額外的請求(或者跳轉其他頁面)來控制流量,接著秒殺業務可以根據消息隊列中有效的請求信息再做后續的處理;
③日志處理->比如kafka消息隊列,其最初設計是為了處理日志,大數據中應用的比較多,當日志數據采集的時候,定時寫入kafka隊列,然后kafka對數據進行儲存,轉發等處理;
④服務解耦->接著上面秒殺話題,假設用戶搶到,會有訂單order服務,商品product服務,用戶下單后,order服務需要通知product服務,如果order服務直接調用product服務的接口,這兩個服務之間是耦合的;那么使用MQ,用戶下單后,order完成持久化并將消息寫入MQ隊列,返回order訂單完成,product服務訂閱MQ隊列中order的消息,采用推拉的方式獲取order下單信息,product服務根據order下單的信息,進行相關product商品的信息的變動(扣庫存),如果過程中product服務不能正常執行,也不會影響order服務,因為order服務寫入MQ隊列之后,就不在關心其他訂閱服務的后續操作了,這樣就現實了服務解耦;
?
貳
就用order,product應用來做測試
order 服務
第一步老套路先引入maven依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency>第二步yml配置還是和上篇差不多,將rabbitmq的配置寫入了碼云git倉庫里,利用SpringCloud Bus讀取
spring:application:name: ordercloud:config:discovery:enabled: trueservice-id: CONFIGprofile: deveureka:client:service-url:defaultZone: http://localhost:8761/eureka/希望碼云git早點支持動態SpringCloud Bus,能用還是能用,先用著,自己手動post請求好了
MQ接收方: 新建一個ReceiverMsg類,用來測試接收MQ的消息
package com.cloud.order.MQmsg;import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component;@Component @Slf4j public class ReceiverMsg {//此處注解指定去獲取名為myQueue的queues隊列消息@RabbitListener(queues = "myQueue")public void printMQ(String message){log.info("【隊列消息】ReceiverMsg ,printMQ={}",message);}}MQ發送方: 這邊直接寫在單元測試中,測試是否能成功,代碼如下
package order;import com.cloud.order.ServerApplication; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.amqp.core.AmqpTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner;//由于之前對項目進行了項目多模塊化,運行單元測試的時候需要引導main啟動類 //沒有可以不考慮classes = ServerApplication.class @SpringBootTest(classes = ServerApplication.class) @RunWith(SpringRunner.class) public class MQTest extends OrderApplicationTests{//AmqpTemplate 操作MQ的API@Autowiredprivate AmqpTemplate amqpTemplate;@Testpublic void send() {amqpTemplate.convertAndSend("myQueue","hello , MQ");}}RabbitMQ : 開啟docker中的rabbitmq,在http://192.168.99.100:15672/#/queues中新增一個名為myQueue的隊列,用于上面測試
啟動服務,可以看到有已經有兩個SpringCloudBus隊列了,一個是SpringCloud Config,一個是上面的order服務,注冊中心eureka一直都是開啟狀態
接著執行單元測試,在myQueue中的波動,說明有流量:?↓↓↓
調用方法中的print,也在控制臺中打印日志 :?↓↓↓
?
循序漸進,每次操作推拉隊列信息的時候,需要方法寫一下,rabbitmq面板中手動加一次,肯定是很lower的
將ReceiverMsg類中的注解,改成以下方式,即可自動批量創建Queue
@RabbitListener(queuesToDeclare = {@Queue("myQueue"),@Queue("myQueue2")})啟動項目后,即可生成Queue
?
Exchange交換機,消息不直接發送到隊列,而是發送到了交換機,通過隊列綁定交換機轉給隊列
如果需要綁定Exchange,可以改動注解
@RabbitListener(bindings = @QueueBinding(value = @Queue("myQueue"),exchange = @Exchange("MyExchange") ))?
繼續order服務中,假設有很多賣方參與,賣奶茶的、賣mac的等等
不同賣方服務會發出不同的MQ消息,比如賣奶茶的只關心奶茶訂單、賣mac的只關心mac訂單,相互不關心其他的組的信息,機子跑不動了,就模擬多服務處理方式?↓↓↓
接收方:?
@Component @Slf4j public class ReceiverMsg {@RabbitListener(bindings = @QueueBinding(key = "milkTea",value = @Queue("milkTeaOrder"),exchange = @Exchange("MyOrder")))public void milkTeaMQ(String message){log.info("【隊列消息】ReceiverMsg.milkTeaMQ ,milkTea={}",message);}@RabbitListener(bindings = @QueueBinding(key = "mac",value = @Queue("macOrder"),exchange = @Exchange("MyOrder")))public void macMQ(String message){log.info("【隊列消息】ReceiverMsg.macMQ ,macMQ={}",message);} }測試 發送方:
@SpringBootTest(classes = ServerApplication.class) @RunWith(SpringRunner.class) public class MQTest extends OrderApplicationTests{@Autowiredprivate AmqpTemplate amqpTemplate;@Testpublic void sendMilkTea() {//第一個參數exchange; 第二個參數key; 第三個參數發送的msgamqpTemplate.convertAndSend("myOrder","milkTea","hello , milkTeaMQ");}@Testpublic void sendMac() {amqpTemplate.convertAndSend("myOrder","mac","hello , macMQ");} }?
以上是RabbitMQ的基礎使用學習,還有很多高級內容,比如消息延遲處理,優先級等等
之后慢慢研究,有相關學習的同學,可以分享一下地址,Mark一起學習學習,謝謝
?
----------------------------------------------------------------
轉載于:https://my.oschina.net/u/3829444/blog/1836946
總結
以上是生活随笔為你收集整理的SpringCloud 微服务 (十) 消息队列MQ 基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端组件库 - 搭建web app常用的
- 下一篇: Web前端入门第 61 问:JavaSc