一、同步通訊和非同步通訊
微服務間通訊有同步和非同步兩種方式:
一)、同步通訊
我們之前學習的Feign呼叫就屬於同步方式,雖然呼叫可以實時得到結果,但存在下面的問題:
同步呼叫的優點:- 時效性較強,可以立即得到結果
同步呼叫的問題:
- 耦合度高:每次加入新的需求,都要修改原來的程式碼;
- 效能和吞吐能力下降:呼叫者需要等待服務提供者響應,如果呼叫鏈過長則響應時間等於每次呼叫的時間之和;
- 有額外的資源消耗:呼叫鏈中的每個服務在等待響應過程中,不能釋放請求佔用的資源,高併發場景下會極度浪費系統資源;
- 有級聯失敗問題:如果服務提供者出現問題,所有呼叫方都會跟著出問題,如同多米諾骨牌一樣,迅速導致整個微服務叢集故障;
二)、非同步通訊
非同步呼叫則可以避免上述問題:
我們以購買商品為例,使用者支付後需要呼叫訂單服務完成訂單狀態修改,呼叫物流服務,從倉庫分配響應的庫存並準備發貨。
在事件模式中,支付服務是事件釋出者(publisher),在支付完成後只需要釋出一個支付成功的事件(event),事件中帶上訂單id。
訂單服務和物流服務是事件訂閱者(Consumer),訂閱支付成功的事件,監聽到事件後完成自己業務即可。
為了解除事件釋出者與訂閱者之間的耦合,兩者並不是直接通訊,而是有一箇中間人(Broker)。釋出者釋出事件到Broker,不關心誰來訂閱事件。訂閱者從Broker訂閱事件,不關心誰發來的訊息。
Broker 是一個像資料匯流排一樣的東西,所有的服務要接收資料和傳送資料都發到這個匯流排上,這個匯流排就像協議一樣,讓服務間的通訊變得標準和可控。
好處:
- 吞吐量提升:無需等待訂閱者處理完成,響應更快速
- 故障隔離:服務沒有直接呼叫,不存在級聯失敗問題
- 呼叫間沒有阻塞,不會造成無效的資源佔用
- 耦合度極低,每個服務都可以靈活插拔,可替換
- 流量削峰:不管釋出事件的流量波動多大,都由Broker接收,訂閱者可以按照自己的速度去處理事件
缺點:架構複雜了,業務沒有明顯的流程線,不好管理。 需要依賴於Broker的可靠、安全、效能。
二、MQ技術簡介
MQ,中文是訊息佇列(MessageQueue),字面來看就是存放訊息的佇列。也就是事件驅動架構中的Broker。
比較常見的MQ實現:
- ActiveMQ
- RabbitMQ
- RocketMQ
- Kafka
MQ,技術簡介:
- RabbitMQ:公司/社群:Rabbit,開發語言:Erlang,協議支援:AMQP,XMPP,SMTP,STOMP
- ActiveMQ:公司/社群:Apache,開發語言:Java,協議支援:OpenWire,STOMP,REST,XMPP,AMQP
- RocketMQ:公司/社群:阿里,開發語言:Java,協議支援:自定義協議
- Kafka:公司/社群:Apache,開發語言:Scala&Java,協議支援:自定義協議
MQ技術對比:
追求可用性:Kafka、 RocketMQ 、RabbitMQ
追求可靠性:RabbitMQ、RocketMQ
追求吞吐能力:RocketMQ、Kafka
追求訊息低延遲:RabbitMQ、Kafka
三、RabbitMQ的一些概念
MQ的基本結構:
RabbitMQ中的一些角色:
- publisher:生產者
- consumer:消費者
- exchange個:交換機,負責訊息路由
- queue:佇列,儲存訊息
- virtualHost:虛擬主機,隔離不同租戶的exchange、queue、訊息的隔離
四、安裝RabbitMQ
我們使用Docker在Centos7中安裝。
步驟一:下載映象
方式一:線上拉取
docker pull rabbitmq:*.*-management
方式二:從本地載入
找到映象包:mq.tar
上傳到虛擬機器中後,使用命令載入映象即可:
docker load -i mq.tar
步驟二: 安裝MQ
執行下面的命令來執行MQ容器:
docker run \ -e RABBITMQ_DEFAULT_USER= rbmq \ -e RABBITMQ_DEFAULT_PASS=123456 \ -v mq-plugins:/plugins \ --name mq \ --hostname mq \ -p 15672:15672 \ -p 5672:5672 \ -d \ rabbitmq:*.*-management