消息服務:MQ使用場景與選型對比
在前面的文章中,我們實現了用戶微服務、商品微服務和訂單微服務之間的遠程調用,并且實現了服務調用的負載均衡。也基于阿里開源的Sentinel實現了服務的限流與容錯,并詳細介紹了Sentinel的核心技術與配置規則。
簡單介紹了服務網關,并對SpringCloud Gateway的核心架構進行了簡要說明,也在項目中整合了SpringCloud
Gateway網關實現了通過網關訪問后端微服務,同時,也基于SpringCloud Gateway整合Sentinel實現了網關的限流功能,詳細介紹了SpringCloud Gateway網關的核心技術。
在鏈路追蹤章節,我們開始簡單介紹了分布式鏈路追蹤技術與解決方案,隨后在項目中整合Sleuth實現了鏈路追蹤,并使用Sleuth整合ZipKin實現了分布式鏈路追蹤的可視化 。
今天,我們正式進入消息服務章節,首先,我們來簡單的聊聊MQ的使用場景,引入MQ后的注意事項以及MQ的選型對比。
本章總覽
MQ的使用場景
MQ的英文全稱是Message Queue,翻譯成中文就是消息隊列,隊列實現了先進先出(FIFO)的消息模型。通過消息隊列,我們可以實現多個進程之間的通信,例如,可以實現多個微服務之間的消息通信。MQ的最簡模型就是生產者生產消息,將消息發送到MQ,消息消費者訂閱MQ,消費消息。
MQ的使用場景通常包含:異步解耦、流量削峰。
異步解耦
關于異步的場景,我們這里舉一個用戶下單成功后,向用戶發送通知消息,為用戶增加積分和優惠券的場景。
同步耦合場景分析
如果是同步調用的場景,則具體業務為:當用戶提交訂單成功后,訂單系統會調用通知系統為用戶發送消息通知,告知用戶下單成功,訂單系統調用積分系統為用戶增加積分,訂單系統調用優惠券系統為用戶增加優惠券。整個調用流程如下所示。
通過上圖的分析,可以看到,用戶調用訂單系統下單時,總共會經過8個步驟。并且每個步驟都是緊密耦合在一起串行執行,如下所示。
此時,訂單系統、通知系統、積分系統和優惠券系統是緊密耦合在一起的,訂單系統下單、通知系統發通知、積分系統發積分和優惠券系統發優惠券,四個任務全部完成后,才會給用戶返回提交訂單的結果信息。
用戶提交訂單花費的總時間為調用訂單系統下單的時間+訂單系統調用通知系統發送通知的時間+訂單系統調用積分系統發放積分的時間+訂單系統調用優惠券系統發放優惠券的時間。
注意:這里為了更好的說明系統之間串行執行的問題,忽略了網絡的延遲時間。
這種串行化的系統執行方式,在高并發、大流量場景下是不可取的。另外,如果其中一個系統異常或者宕機,勢必會影響到訂單系統的可用性。在系統維護上,只要任意一個系統的接口發生變動,訂單系統的邏輯也要跟著發生變動。
異步解耦場景分析
既然在高并發、大流量場景下使用訂單系統直接串行調用通知系統、積分系統和優惠券系統的方式不可取。那我們是否能夠使用異步解耦的方式呢。
其實,在用戶提交訂單的場景中,用戶最關心的是自己的訂單是否提交成功,由于下單時,訂單系統會直接返回是否下單成功的提示。
對于通知、積分和優惠券可以以異步的方式延后一小段時間執行。并且通知系統、積分系統和優惠券系統之間不存在必然的業務關聯邏輯,它們之間可以以并行的方式執行。
所以,可以使用MQ將訂單系統與通知系統、積分系統和優惠券系統進行解耦,用戶調用訂單系統的接口下單時,訂單系統向數據庫寫入訂單數據后,向MQ寫入消息,就可以直接返回給用戶下單成功的提示,此時通知系統、積分系統和優惠券系統都訂閱MQ中的消息,收到消息后各自執行自身的業務邏輯即可。
當引入MQ進行異步解耦之后,用戶調用訂單系統的接口下單,訂單系統執行完業務邏輯將訂單數據入口,會向MQ發送一條消息,隨后便直接返回用戶下單成功的提示。通知系統、積分系統和優惠券系統會同時訂閱MQ中的消息,當收到消息時,它們各自會執行自身的業務邏輯,并且它們是以并行的方式執行各自的業務邏輯。
從執行的時間線上可以看出,當引入MQ進行異步解耦之后,通知系統、積分系統、優惠券系統和訂單系統回復響應都是并行執行的,大大提高系統的執行性能。
并且解耦后,任意一個系統異常或者宕機,都不會影響到訂單系統的可用性。只要訂單系統與其他系統提前約定好發送的消息格式和消息內容,后續任意一個系統的業務邏輯變動,幾乎都不會影響到訂單系統的邏輯。
流量削峰
MQ在高并發、大流量的場景下可以用作削峰填谷的利器,例如,12306的春運搶票場景、高并發秒殺場景、雙十一和618的大促場景等。
在高并發、大流量業務場景下,瞬間會有大量用戶的請求涌入系統,如果不對這些流量做處理的話,直接讓這些流量進入下游系統,則很可能由于下游系統無法支撐如此高的并發而導致系統崩潰或宕機。為了解決這些問題,可以引入MQ進行流量的削峰填谷。
將流量發送到MQ中后,下游系統根據自身的處理能力進行消費即可。保證了下游系統的高可用性。
引入MQ后的注意事項
引入MQ最大的優點就是異步解耦和流量削峰,但是引入MQ后也有很多需要注意的事項和問題,主要包括:系統的整體可用性降低、系統的復雜度變高、引入了消息一致性的問題。
系統的整體可用性降低
在對一個系統進行架構設計時,引入的外部依賴越多,系統的穩定性和可用性就會降低。系統中引入了MQ,部分業務就會出現強依賴MQ的現象,此時,如果MQ宕機,則部分業務就會變得不可用。所以,引入MQ時,我們就要考慮如何實現MQ的高可用。
系統的復雜度變高
引入MQ后,會使之前的同步接口調用變成通過MQ的異步調用,在實際的開發過程中,異步調用會比同步調用復雜的多。并且異步調用出現問題后,重現問題,定位問題和解決問題都會比同步調用復雜的多。
并且引入MQ后,還要考慮如何保證消息的順序等問題。
消息一致性問題
引入MQ后,不得不考慮的一個問題就是消息的一致性問題。這期間就要考慮如何保證消息不丟失,消息冪等和消息數據處理的冪等性問題。
MQ選型對比
目前,在行業內使用的比較多的MQ包含RabbitMQ、Kafka和RocketMQ。這里,我將三者的對比簡單整理了個表格,如下所示。
消息中間件(MQ) | 優點 | 缺點 | 使用場景 |
RabbitMQ | 功能全面、消息的可靠性比較高 | 吞吐量低,消息大量積累會影響性能,使用的開發語言是erlang,不好定制功能。 | 規模不大的場景 |
Kafka | 吞吐量最高,性能最好,集群模式下高可用 | 功能上比較單一,會丟失部分數據 | 日志分析,大數據場景 |
RocketMQ | 吞吐量高,性能高,可用性高,功能全面。使用Java語言開發,容易定制功能。 | 開源版不如阿里云上版,文檔比較簡單。 | 幾乎支持所有場景,包含大數據場景和業務場景。 |