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

本文來自網易雲信團隊的技術分享,原創發表於網易雲信公衆號,原文鏈接:mp.weixin.qq.com/s/LT2dASI7QVpcOVxDAsMeVg,收錄時有改動。

1、引言

在不瞭解IM技術的人眼裏,羣聊是再平常不過的功能而已,萬人羣聊?應該也不難實現吧?!

確實,從前端功能界面上來看,羣聊無非就是個循環向羣員發送消息的一對多聊天消息分發模式而已,難在何處?

真實的情況是,羣聊是IM系統中的高難度技術點之一。難在哪?難在服務端!從某種角度上說,羣聊功能的架構設計和技術實現的品質,可以代表這款IM軟件的技術水平。

羣聊從後臺的技術實現上說,至少有以下難點:

1)如何高效地進行大量羣員消息的分發?

2)如何高效地管理羣員的在線狀態?

3)如何高效地讀取羣員的在線狀態?

4)集羣系統中,如何高效地保證羣員消息的準確送達?

5)羣聊消息該擴散寫還是擴散讀?

6)如何保證大量羣聊消息分發的情況下不影響單聊消息體驗?

7)如何應對大羣突發事件下的性能負載?

.... ....

目前,市面上主流的IM產品中,微信羣是500人上限,QQ羣是3000人上限(3000人羣是按年付費升級,很貴,不是爲一般用戶準備的)。一方面,從產品的定義上羣成員數量不應過多,另一方面,技術成本也是個不可迴避的因素。萬人羣這種超大規模羣的技術難度,更是難已想象。

本文內容是網易雲信團隊爲了響應萬人羣聊功能需求,在設計實現萬人羣聊技術方案中總結的技術實踐,藉此機會分享給各IM開發者同行。

(本文同步發佈於:http://www.52im.net/thread-2707-1-1.html

學習交流:

- 即時通訊/推送技術開發交流5羣:215477170[推薦]

- 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM

2、概述

隨着移動互聯網的發展,即時通訊服務被廣泛應用到各個行業,客戶業務快速發展,傳統百人或千人上限的羣聊已經無法滿足很多業務發展需求,因此網易雲信IM推出萬人羣服務。

萬人羣場景需要解決以下問題:

1)消息需要按1:9999的比例進行轉發投遞,按常規消息處理流程將產生大量的子任務,對系統吞吐量的要求極高;

2)在微服務系統架構下,如果不採用一些優化方案,服務以及存儲(DB、緩存等)之間的QPS和網絡流量將非常高;

3)以羣爲單位的緩存(如羣成員列表)內存存儲開銷較大(假設一個成員200Byte,萬人羣約2MB);

4)羣成員登錄後需要同步羣離線消息,智能手機上App前後臺切換產生的較多登錄同步消息協議,因此需要優化消息同步方案。

爲了解決以上問題,萬人羣技術方案採用了“聚合+分層/組+增量”的設計思路:

3、萬人羣消息的處理流程

1)按羣維護在線羣成員信息,主要包含兩部分(可以理解爲兩個緩存集合):

a. 羣成員在線信息:即用戶在線狀態變化(上線、下線)時,更新相應羣的在線狀態信息(即動態維護羣有哪些成員在線);

b. 成員IM長連接信息:即用戶新登錄時,更新用戶的Link信息(即登錄所在Link的地址信息,消息轉發時根據Link地址路由消息)。

2)IM Server收到羣消息後,按羣ID將消息路由到“羣消息服務”模塊;

3)羣消息模塊檢查並預處理消息內容,然後通過“羣成員在線狀態”服務獲取在線成員,完成消息轉發的基礎工作。爲了減少羣消息模塊和羣在線成員服務之間的網絡流量,採用了“本地緩存+增量同步”的緩存策略,即本地緩存記錄最後更新版本號和時間戳,每次同步羣在線成員前先檢查緩存版本號是否有變更,若有則按最後更新時間增量同步;

4)通過“羣成員在線服務”獲取在線羣成員的Link鏈接信息,按Link分組路由消息(分組路由的原因:同一Link上的全部羣成員只需要路由一條消息即可)。同樣爲了減少網絡開銷,成員Link信息也採用“本地緩存+增量同步”的方案;

5)羣消息採用“漫遊+歷史”的存儲方案,漫遊的消息存儲在分佈式緩存中,歷史消息異步寫入HBase。用戶登錄後可以通過漫遊快速的獲取到最新消息,並可以通過拉取歷史查看更早的消息。

4、萬人羣方案本地緩存增量同步策略

拋開羣在線狀態管理邏輯,羣成員在線狀態服務可以簡單理解爲分佈式集中緩存。

增量同步技術方案如下:

如上圖所示:

1)數據緩存是一個集合,其包含了多個緩存數據項,每一個數據項帶有最後更新時間信息;另外緩存還有一個嚴格遞增的版本號;

2)緩存數據變更(新增、修改、刪除)後,需要增加版本號;

3)本地線程通過緩存管理讀取數據時,管理服務先檢查本地版本號和分佈式緩存中的版本號是否一致,若不一致則按本地最新時間戳增量同步新數據項,並更新本地的版本號和最後更新時間(爲了避免分佈式集中緩存中併發寫入導致的增量時間戳不可靠問題,增量更新時可以將本地記錄的最後更新時間戳向前推移,比如減少20ms);

4)爲避免本地多線程併發讀取相同數據項導致併發更新本地緩存的問題,可以按緩存數據合併更新請求,即解決併發問題還可以減少網絡開銷;

5)緩存數據由大量數據項構成,爲了避免單個緩存數據太大,可以將數據項中的屬性業務場景精簡(冷熱分離),低頻次讀寫的屬性額外緩存。

5、萬人羣水平擴容方案

萬人羣採用大量本地緩存的方案解決消息處理性能和網絡流量的問題,因此本地存儲空間成了方案的瓶頸點。因此我們設計了分組路由的技術方案。

消息按羣ID和路由策略定向路由到指定分組(集羣)上處理,分組由多個計算節點組成,因此方案上可以做到分組內和分組間的水平擴縮容。

6、作爲“雲”服務,網易雲信是如何實現萬人羣所需的計算資源的?

由於萬人羣對計算和存儲資源消耗比較高,在實施和運維方案上也有一定的特殊性,爲了保證業務的可靠性和穩定性,網易雲信是將萬人大羣的能力,僅提供給專屬的雲客戶(普通公有云客戶是無法使用的)。

之所以能從軟硬件基礎設施上爲萬人羣提供保障,網易雲信的IM專有云必須具備以下資源能力:

1)需要專屬的獨立計算資源:保持計算資源獨立,且資源冗餘度比公有云高,且需要保證不會受到公有云上其他客戶業務的影響;

2)需要專屬的獨立運維服務:從而根據客戶業務場景制定最佳的業務監控、彈性擴容、故障遷移等運維方案。

總之,萬人羣聊的實現,過硬的技術方案設計和技術實現只是一方面,基礎計算設施資源和運維能力也是不可或缺。

所以,從今以後,不要隨隨便便就喊萬人羣聊,甚至十萬人羣聊,這不是想實現就能實現的哦!

附錄:更多羣聊相關技術文章

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

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

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

IM羣聊消息如此複雜,如何保證不丟不重?

微信後臺團隊:微信後臺異步消息隊列的優化升級實踐分享

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

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

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

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

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

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

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

IM羣聊機制,除了循環去發消息還有什麼方式?如何優化?

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

>> 更多同類文章 ……

(本文同步發佈於:http://www.52im.net/thread-2707-1-1.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章