IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列
1、引言
消息是互聯網信息的一種表現形式,是人利用計算機進行信息傳遞的有效載體,比如即時通訊網壇友最熟悉的即時通訊消息就是其具體的表現形式之一。
消息從發送者到接收者的典型傳遞方式有兩種:
?
- 1)一種我們可以稱為即時消息:即消息從一端發出后(消息發送者)立即就可以達到另一端(消息接收者),這種方式的具體實現就是平時最常見的IM聊天消息;
- 2)另一種稱為延遲消息:即消息從某端發出后,首先進入一個容器進行臨時存儲,當達到某種條件后,再由這個容器發送給另一端。
在上述“消息傳遞方式2)”中所指的這個容器的一種具體實現就是MQ消息隊列服務。
MQ消息隊列中間件是中大型分布式系統中重要的組件,它主要用來解決:應用解耦、異步消息、流量削鋒等問題,用以實現高性能、高可用、可伸縮和最終一致性架構。目前使用較多的消息隊列有ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ等。MQ消息隊列中間件已被廣泛用于電商、即時通訊、社交等各種中大型分布式應用系統。
在一個典型的IM即時通訊應用中,MQ消息隊列可以用于:
?
- 1)用戶的聊天消息離線存儲環節:因為IM消息的發送屬于高吞吐場景,直接操縱DB很容易就把DB搞掛了,所以離線消息在落地入庫前,可以先扔到MQ消息隊列中,再由單獨部署的消費者來有節奏地存儲到DB中;
- 2)用戶的行為數據收集環節:因為用戶的聊天消息和指令等,可以用于大數據分析,而且基于國家監管要求也是必須要存儲一段時間的,所以此類數據的收集同樣可以用于MQ消息隊列,再由單獨部署的消費者存儲到DB中;
- 3)用戶的操作日志收集環節:log這種數據價值不高,但關鍵時刻又非常有用,而且數據量又很大,要想存儲起來難度很高,這時就輪到Linkedin公司開源的Kafka出場了;
- ....
因此,對于即時通訊開發者來說,正確地理解MQ消息隊列,對于IM或消息推送系統的架構設計、方案選型等都大有裨益。
2、系列文章
- 《IM開發基礎知識補課(三):快速理解服務端數據庫讀寫分離原理及實踐建議》
- 《IM開發基礎知識補課(四):正確理解HTTP短連接中的Cookie、Session和Token》
3、MQ消息隊列的典型應用場景
MQ消息隊列目前在中大型分布式系統實際應用中常用的使用場景主要有:異步處理、應用解耦、流量削鋒和消息通訊四個場景。
?
3.1應用場景1:異步處理
場景說明:一個典型的IM即時通訊系統中,用戶注冊成功后可能需要發送注冊郵件和注冊通知短信。
傳統的做法有兩種:
?
- 1)串行的方式:即將注冊信息寫入數據庫成功后、發送注冊郵件、再發送注冊短信。以上三個任務全部完成后,返回給客戶端;
- 2)并行方式:即將注冊信息寫入數據庫成功后,發送注冊郵件的同時,發送注冊短信。以上三個任務完成后,返回給客戶端。與串行的差別是,并行的方式可以提高處理的時間。
假設三個業務節點每個使用50毫秒,不考慮網絡等其他開銷,則串行方式的時間是150毫秒,并行的時間可能是100毫秒。
因為CPU在單位時間內處理的請求數是一定的,假設CPU1秒內吞吐量是100次。則串行方式1秒內CPU可處理的請求量是7次(1000/150)。并行方式處理的請求量是10次(1000/100)。
小結:如以上案例描述,傳統的方式系統的性能(并發量,吞吐量,響應時間)會有瓶頸。
如何解決這個問題呢?答案是:引入消息隊列,將不是必須的業務邏輯,異步處理。
改造后的架構如下:
按照以上約定,用戶的響應時間相當于是注冊信息寫入數據庫的時間,也就是50毫秒。注冊郵件,發送短信寫入消息隊列后,直接返回,因此寫入消息隊列的速度很快,基本可以忽略,因此用戶的響應時間可能是50毫秒。因此架構改變后,系統的吞吐量提高到每秒20 QPS。比串行提高了3倍,比并行提高了兩倍。
?
3.2應用場景2:應用解耦
場景說明:一個典型的電商購物系統中,用戶下訂單后,訂單系統需要通知庫存系統。
傳統的做法是:訂單系統調用庫存系統的接口。如下圖所示:
傳統模式的缺點:假如庫存系統無法訪問,則訂單減庫存將失敗,從而導致訂單失敗,訂單系統與庫存系統耦合。
如何解決以上問題呢?答案是:引入應用消息隊列后的方案。如下圖:
如上圖所示,大致的原理是:
?
- 訂單系統:用戶下單后,訂單系統完成持久化處理,將消息寫入消息隊列,返回用戶訂單下單成功;
- 庫存系統:訂閱下單的消息,采用拉/推的方式,獲取下單信息,庫存系統根據下單信息,進行庫存操作。
好處就是:假如在下單時庫存系統不能正常使用,也不影響正常下單,因為下單后,訂單系統寫入消息隊列就不再關心其他的后續操作了。實現訂單系統與庫存系統的應用解耦。
?
3.3應用場景3:流量削鋒
流量削鋒也是消息隊列中的常用場景,一般在電商秒殺等大型活動(比如雙11)、團購搶單活動中使用廣泛。
應用場景:秒殺活動,一般會因為流量過大,導致流量暴增,應用掛掉。為解決這個問題,一般需要在應用前端加入消息隊列。
在這種場景下加入消息隊列服務的好處:
?
- 1)可以控制活動的人數;
- 2)可以緩解短時間內高流量壓垮應用。
用戶的請求,服務器接收后,首先寫入消息隊列。假如消息隊列長度超過最大數量,則直接拋棄用戶請求或跳轉到錯誤頁面。秒殺業務根據消息隊列中的請求信息,再做后續處理。
?
3.4應用場景4:日志處理
日志處理是指將消息隊列用在日志處理中,比如Linkedin這種大型職業社交應用架構中Kafka的應用(Kafka就是Linkedin開發并開源的),解決大量日志傳輸的問題。
使用Kafka后的架構簡化如下:
上圖所示的架構原理就是:
?
- 日志采集客戶端:負責日志數據采集,定時寫入Kafka隊列;
- Kafka消息隊列:負責日志數據的接收,存儲和轉發;
- 日志處理應用:訂閱并消費kafka隊列中的日志數據。
?
3.5應用場景5:即時消息通訊
即時消息通訊是指,消息隊列一般都內置了高效的通信機制,因此也可以用在純的即時消息通訊場景。比如實現點對點消息隊列或者IM聊天室等(但Jack Jiang認為,在中大型IM系統中,MQ并不適合這么用,具體的討論請見:《請教可以使用MQ消息隊列中間件做即時通訊系統嗎?》)。
- 點對點通訊:客戶端A和客戶端B使用同一隊列,進行消息通訊;
- 聊天室通訊:客戶端A,客戶端B,客戶端N訂閱同一主題,進行消息發布和接收。實現類似聊天室效果。
以上實際是消息隊列的兩種消息模式,點對點或發布訂閱模式。模型為示意圖,供參考。
4、MQ消息隊列的常見消息模式
常見的MQ消息隊列消息模式有:
?
- 1)P2P模式;
- 2)Pub/sub模式(也就是常說的“發布/訂閱”模式);
- 3)推(Push)模式和拉(Pull)模式。
下面將逐個介紹這幾種常消息模式。
?
4.1P2P模式
P2P模式包含三個角色:
?
- 1)消息隊列(Queue);
- 2)發送者(Sender);
- 3)接收者(Receiver)。
每個消息都被發送到一個特定的隊列,接收者從隊列中獲取消息。隊列保留著消息,直到他們被消費或超時。
P2P消息模式的特點:
每個消息只有一個消費者(Consumer)(即一旦被消費,消息就不再在消息隊列中)發送者和接收者之間在時間上沒有依賴性,也就是說當發送者發送了消息之后,不管接收者有沒有正在運行,它不會影響到消息被發送到隊列接收者在成功接收消息之后需向隊列應答成功 如果希望發送的每個消息都會被成功處理的話,那么需要P2P模式。
?
4.2Pub/sub模式
如上圖所示,此消息模式包含三個角色:
?
- 1)主題(Topic);
- 2)發布者(Publisher);
- 3)訂閱者(Subscriber)。
多個發布者將消息發送到Topic,系統將這些消息傳遞給多個訂閱者。
Pub/Sub的特點:
每個消息可以有多個消費者發布者和訂閱者之間有時間上的依賴性。針對某個主題(Topic)的訂閱者,它必須創建一個訂閱者之后,才能消費發布者的消息。為了消費消息,訂閱者必須保持運行的狀態。為了緩和這樣嚴格的時間相關性,有些MQ消息隊列(比如RabbitMQ)允許訂閱者創建一個可持久化的訂閱。這樣,即使訂閱者沒有被激活(運行),它也能接收到發布者的消息。如果希望發送的消息可以不被做任何處理、或者只被一個消息者處理、或者可以被多個消費者處理的話,那么可以采用Pub/Sub模型。
?
4.3推模式和拉模式
推(push)模式是一種基于C/S機制、由服務器主動將信息送到客戶器的技術。
在Push模式應用中,服務器把信息送給客戶器之前,并沒有明顯的客戶請求。push事務由服務器發起。push模式可以讓信息主動、快速地尋找用戶/客戶器,信息的主動性和實時性比較好。但精確性較差,可能推送的信息并不一定滿足客戶的需求。
Push模式不能保證能把信息送到客戶器,因為推模式采用了廣播機制,如果客戶器正好聯網并且和服務器在同一個頻道上,推送模式才是有效的。
Push模式無法跟蹤狀態,采用了開環控制模式,沒有用戶反饋信息。在實際應用中,由客戶器向服務器發送一個申請,并把自己的地址(如IP、port)告知服務器,然后服務器就源源不斷地把信息推送到指定地址。在多媒體信息廣播中也采用了推模式。
拉(Pull)模式與推(Push)模式相反,是由客戶器主動發起的事務。服務器把自己所擁有的信息放在指定地址(如IP、port),客戶器向指定地址發送請求,把自己需要的資源“拉”回來。不僅可以準確獲取自己需要的資源,還可以及時把客戶端的狀態反饋給服務器。
5、主流的MQ消息隊列技術選型對比
一份主流MQ技術對比清單:
?
?
5.1Kafka
Kafka是Linkedin開源的MQ系統(現已是Apache下的一個子項目),它是一個高性能跨語言分布式發布/訂閱消息隊列系統,主要特點是基于Pull的模式來處理消息消費,追求高吞吐量,一開始的目的就是用于日志收集和傳輸,0.8開始支持復制,不支持事務,適合產生大量數據的互聯網服務的數據收集業務。
Kafka還具有以下特性:
?
- 1)快速持久化,可以在O(1)的系統開銷下進行消息持久化;
- 2)高吞吐,在一臺普通的服務器上既可以達到10W/s的吞吐速率;
- 3)完全的分布式系統,Broker、Producer、Consumer都原生自動支持分布式,自動實現負載均衡;
- 4)支持Hadoop數據并行加載,對于像Hadoop的一樣的日志數據和離線分析系統,但又要求實時處理的限制,這是一個可行的解決方案。Kafka通過Hadoop的并行加載機制統一了在線和離線的消息處理。
Apache Kafka相對于ActiveMQ是一個非常輕量級的消息系統,除了性能非常好之外,還是一個工作良好的分布式系統。
?
5.2RabbitMQ
RabbitMQ是使用Erlang語言開發的開源消息隊列系統,基于AMQP協議來實現。AMQP的主要特征是面向消息、隊列、路由(包括點對點和發布/訂閱)、可靠性、安全。AMQP協議更多用在企業系統內,對數據一致性、穩定性和可靠性要求很高的場景,對性能和吞吐量的要求還在其次。
RabbitMQ本身支持很多的協議:AMQP,XMPP, SMTP, STOMP,也正因如此,它非常重量級,更適合于企業級的開發。同時實現了Broker構架,這意味著消息在發送給客戶端時先在中心隊列排隊。對路由,負載均衡或者數據持久化都有很好的支持。
?
5.3RocketMQ
RocketMQ是阿里開源的消息中間件,它是純Java開發,具有高吞吐量、高可用性、適合大規模分布式系統應用的特點。RocketMQ思路起源于Kafka,但并不是Kafka的一個Copy,它對消息的可靠傳輸及事務性做了優化,目前在阿里集團被廣泛應用于交易、充值、流計算、消息推送、日志流式處理、binglog分發等場景。
?
5.4ZeroMQ
ZeroMQ只是一個網絡編程的Pattern庫,將常見的網絡請求形式(分組管理,鏈接管理,發布訂閱等)模式化、組件化,簡而言之socket之上、MQ之下。對于MQ來說,網絡傳輸只是它的一部分,更多需要處理的是消息存儲、路由、Broker服務發現和查找、事務、消費模式(ack、重投等)、集群服務等。
ZeroMQ是號稱最快的消息隊列系統,尤其針對大吞吐量的需求場景。ZeroMQ能夠實現RabbitMQ不擅長的高級/復雜的隊列,但是開發人員需要自己組合多種技術框架,技術上的復雜度是對這MQ能夠應用成功的挑戰。ZeroMQ具有一個獨特的非中間件的模式,你不需要安裝和運行一個消息服務器或中間件,因為你的應用程序將扮演這個服務器角色。你只需要簡單的引用ZeroMQ程序庫,可以使用NuGet安裝,然后你就可以愉快的在應用程序之間發送消息了。但是ZeroMQ僅提供非持久性的隊列,也就是說如果宕機,數據將會丟失。其中,Twitter的Storm 0.9.0以前的版本中默認使用ZeroMQ作為數據流的傳輸(Storm從0.9版本開始同時支持ZeroMQ和Netty作為傳輸模塊)。
?
5.5小結
RabbitMQ/Kafka/ZeroMQ 都能提供消息隊列服務,但有很大的區別。
在面向服務架構中通過消息代理(比如 RabbitMQ / Kafka等),使用生產者-消費者模式在服務間進行異步通信是一種比較好的思想。
因為服務間依賴由強耦合變成了松耦合。消息代理都會提供持久化機制,在消費者負載高或者掉線的情況下會把消息保存起來,不會丟失。就是說生產者和消費者不需要同時在線,這是傳統的請求-應答模式比較難做到的,需要一個中間件來專門做這件事。其次消息代理可以根據消息本身做簡單的路由策略,消費者可以根據這個來做負載均衡,業務分離等。
缺點也有,就是需要額外搭建消息代理集群(但優點是大于缺點的 ) 。
ZeroMQ 和 RabbitMQ/Kafka 不同,它只是一個異步消息庫,在套接字的基礎上提供了類似于消息代理的機制。使用 ZeroMQ 的話,需要對自己的業務代碼進行改造,不利于服務解耦。
RabbitMQ 支持 AMQP(二進制),STOMP(文本),MQTT(二進制),HTTP(里面包裝其他協議)等協議。Kafka 使用自己的協議。
Kafka 自身服務和消費者都需要依賴 Zookeeper。
RabbitMQ 在有大量消息堆積的情況下性能會下降,Kafka不會。畢竟AMQP設計的初衷不是用來持久化海量消息的,而Kafka一開始是用來處理海量日志的。
總的來說,RabbitMQ 和 Kafka 都是十分優秀的分布式的消息代理服務,只要合理部署,基本上可以滿足生產條件下的任何需求。
?
網易云信,你身邊的即時通訊和音視頻技術專家,了解我們,請戳網易云信官網
想要行業洞察和技術干貨,請關注網易云信博客
本文轉載自52im,作者:JackJiang
總結
以上是生活随笔為你收集整理的IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IM开发基础知识补课(四):正确理解HT
- 下一篇: 音视频技术“塔尖”之争,网易云信如何C位