IM技術分享:萬人群聊訊息投遞方案的思考和實踐

語言: CN / TW / HK

本文由融雲技術團隊原創分享,原題“技術實踐丨萬人群聊的訊息分發控速方案”,為使文章更好理解,內容有修訂。

1、引言

傳統意義上的IM群聊,通常都是像微信這樣的500人群,或者QQ的2000人群(QQ有3000人群,但那是單獨收費的,也就意味著它並非無門檻標配,能用上的人並不多)。

自從國外某號稱“世界上最安全的IM”搞出萬人群聊之後,萬人群迅速被國內的使用者們接受。伴隨著移動網際網路的發展,即時通訊服務被廣泛應用於各個行業(以經不再侷限於傳統IM社交應用領域),隨著業務快速發展,傳統百人、千人上限的群聊已經無法滿足很多業務場景需求,所以萬人甚至十萬人的超大群也算是相伴而生、順應潮流。 

▲ “紙飛機”的萬人群(開發人員顫抖中...)

IM群聊一直是IM應用中比較有難度的熱點技術之一,通常意義的群聊,無非就是500人群、1000人群、2000人群這樣,技術實現上比單聊要複雜不少。然而對於萬人群聊(甚至十萬人群聊)來說,相比百人、千人群聊,技術實現上那幾乎是另一個技術維度的事情,難度要高很多。

本文根據融雲技術團隊的實踐經驗,總結了萬人群聊訊息投遞方案的一些思考和實踐,希望能給你帶來啟發。

2、相關文章

萬人群聊有關的技術文章還可讀一讀以下這篇:

  1. 網易雲信技術分享:IM中的萬人群聊技術方案實踐總結
  2. 企業微信的IM架構設計揭祕:訊息模型、萬人群、已讀回執、訊息撤回等
  3. 阿里釘釘技術分享:企業級IM王者——釘釘在後端架構上的過人之處

融雲技術團隊分享的其它文章:

  1. 融雲技術分享:融雲安卓端IM產品的網路鏈路保活技術實踐
  2. 融雲技術分享:全面揭祕億級IM訊息的可靠投遞機制
  3. 融雲技術分享:基於WebRTC的實時音視訊首幀顯示時間優化實踐
  4. IM訊息ID技術專題(三):解密融雲IM產品的聊天訊息ID生成策略

3、超大群面臨的技術挑戰

與百人群、千人群相比,萬人、甚至十萬人超大群,大幅提升了群的觸達人數,對於很多業務場景來說,好處不言而喻。

然而單群成員如此之大,給 IM 系統的流量衝擊非常巨大,技術難度可想而之。我們先來分析一下超大群的技術挑戰。

以一個萬人群的模型為例:

  • 1)如果群中有人發了訊息,那麼這條訊息需要按照 1:9999 的比例進行分發投遞,如果我們按照常規訊息的處理流程,那麼訊息處理服務壓力巨大;
  • 2)訊息量大的情況下,服務端向客戶端直推訊息的處理速度將會成為系統瓶頸,而一旦使用者的訊息下發佇列造成了擠壓,會影響到正常的訊息分發,也會導致服務快取使用量激增;
  • 3)在微服務架構中,服務以及儲存(DB,快取)之間的 QPS 和網路流量也會急劇增高;
  • 4)以群為單位的訊息快取,記憶體和儲存開銷較大(訊息體的儲存被放大了萬倍)。

基於這些技術挑戰,要想真正達成超大群的技術目標,勢必要做特定的技術優化來應對。

4、一般群聊的訊息投遞模型

先來看看普通群聊的訊息投遞模型。

我們的普通群聊訊息投遞模型如下圖所示:

如上圖所示,當用戶在普通群裡發了一條訊息後,投遞路徑是:

  • 1)訊息先到群組服務;
  • 2)然後通過群組服務快取的群關係,鎖定這條訊息最終需要分發的目標使用者;
  • 3)再根據一定的策略分發到訊息服務上;
  • 4)訊息服務再根據使用者的線上狀態和訊息狀態來判斷這條訊息是直推、通知拉取還是轉 Push,最終投遞給目標使用者。

普通群聊的訊息投遞,正像您期待的那樣,基本上大家的實現手段都大差不差。然而對於萬人群來說,這顯然還不夠。

下面來看看我們針對萬人群聊訊息投遞的技術優化手段。

5、萬人群聊訊息投遞優化手段1:控速

針對萬人群的訊息投遞,我們的一個主要手段就是控速。

如上圖所示。

首先:我們會根據伺服器的核數來建立多個群訊息分發佇列,這些佇列我們設定了不同的休眠時間以及不同的消費執行緒數。

通俗來講,可以將佇列這樣劃分為快、中、慢等佇列。

其次:我們根據群成員數量的大小來將所有群對映到相應的佇列中。

規則是:

  • 1)小群對映到快佇列中;
  • 2)大群對映到相應的慢佇列中。

然後:小群由於人數少,對服務的影響很小,所以服務利用快佇列快速的將群訊息分發出去,而大群群訊息則利用慢佇列的相對高延時來起到控速的作用。

6、萬人群聊訊息投遞優化手段2:合併

在本文第3節中提到的萬人群聊所面臨的技術挑戰,最主要的挑戰其實就是訊息進行擴散分發投遞後,訊息被克隆出N條,訊息流量瞬間被放大。

舉個例子:當一條群訊息傳送到 IM 伺服器後,需要從群組服務投遞給訊息服務,如果每一個群成員都投遞一次,並且投遞的群訊息內容是一致的話,那肯定會造成相應的資源浪費和服務壓力。

那麼針對這種情況,我們的解決方案就是進行訊息合併投遞。

原理就是:服務落點計算中我們使用的是一致性雜湊,群成員落點相對固定,所以落點一致的群成員我們可以合併成一次請求進行投遞,這樣就大幅提高了投遞效率同時減少了服務的壓力。

下圖是雲信團隊分享的萬人群訊息合併投遞邏輯:

▲ 上圖引用自《IM中的萬人群聊技術方案實踐總結

如上圖所示,雲信團隊的萬人群訊息合併投遞方案是:按Link分組路由訊息,同一Link上的全部群成員只需要路由一條訊息即可。

7、十萬、百萬級的超大群處理方案

在實際群聊業務中,還有一種業務場景是超大規模群,這種群的群人數達到了數十萬甚至上百萬。

這種群如果按照上述的投投遞方案,勢必仍會造成訊息節點的巨大壓力。

比如我們有一個十萬人的群,訊息節點五臺,訊息服務處理訊息的上限是一秒鐘 4000 條,那每臺訊息節點大約會分到 2 萬條群訊息,這已大大超出了訊息節點的處理能力。

所以為了避免上述問題,我們會將群成員上線超過3000的群識別為萬人群、超級群,這種級別的群可以根據伺服器數量和伺服器配置相應做調整針對這種超級群會用特殊的佇列來處理群訊息的投遞。

這個特殊的佇列1秒鐘往後端訊息服務投遞的訊息數是訊息服務處理上限的一半(留相應的能力處理其他訊息),如果單臺訊息服務處理的 QPS 上限是 4000,那群組服務一秒往單臺訊息服務最多投遞 2000 條。

8、寫在最後

未來,我們也會針對群訊息進行引用投遞,對於大群裡發的訊息體比較大的訊息,我們給群成員只分發和快取訊息的索引,比如 MessageID。等群成員真正拉取群訊息時再從將訊息組裝好給客戶端分發下去。這樣做會節省分發的流量以及儲存的空間。

隨著網際網路的發展,群組業務的模型和壓力也在不停地擴充套件,後續可能還會遇到更多的挑戰,當然也會不斷迭代出更優的處理方式來應對。

附錄:更多IM群聊技術文章

快速裂變:見證微信強大後臺架構從0到1的演進歷程(一)

如何保證IM實時訊息的“時序性”與“一致性”?

IM單聊和群聊中的線上狀態同步應該用“推”還是“拉”?

IM群聊訊息如此複雜,如何保證不丟不重?

微信後臺團隊:微信後臺非同步訊息佇列的優化升級實踐分享

移動端IM中大規模群訊息的推送如何保證效率、實時性?

現代IM系統中聊天訊息的同步和儲存方案探討

關於IM即時通訊群聊訊息的亂序問題討論

IM群聊訊息的已讀回執功能該怎麼實現?

IM群聊訊息究竟是存1份(即擴散讀)還是存多份(即擴散寫)?

一套高可用、易伸縮、高併發的IM群聊、單聊架構方案設計實踐

[技術腦洞] 如果把14億中國人拉到一個微信群裡技術上能實現嗎?

IM群聊機制,除了迴圈去發訊息還有什麼方式?如何優化?

網易雲信技術分享:IM中的萬人群聊技術方案實踐總結

阿里釘釘技術分享:企業級IM王者——釘釘在後端架構上的過人之處

IM群聊訊息的已讀未讀功能在儲存空間方面的實現思路探討

直播系統聊天技術(一):百萬線上的美拍直播彈幕系統的實時推送技術實踐之路

直播系統聊天技術(二):阿里電商IM訊息平臺,在群聊、直播場景下的技術實踐

直播系統聊天技術(三):微信直播聊天室單房間1500萬線上的訊息架構演進之路

直播系統聊天技術(四):百度直播的海量使用者實時訊息系統架構演進實踐

企業微信的IM架構設計揭祕:訊息模型、萬人群、已讀回執、訊息撤回等

融雲IM技術分享:萬人群聊訊息投遞方案的思考和實踐

>> 更多同類文章 ……

本文已同步釋出於“即時通訊技術圈”公眾號。

同步釋出連結是:http://www.52im.net/thread-3687-1-1.html

「其他文章」