本文來自網易雲信團隊的技術分享,原創發表於網易雲信公衆號,原文連接:mp.weixin.qq.com/s/LT2dASI7QVpcOVxDAsMeVg,收錄時有改動。php
在不瞭解IM技術的人眼裏,羣聊是再日常不過的功能而已,萬人羣聊?應該也不難實現吧?!html
確實,從前端功能界面上來看,羣聊無非就是個循環向羣員發送消息的一對多聊天消息分發模式而已,難在何處?前端
真實的狀況是,羣聊是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》
隨着移動互聯網的發展,即時通信服務被普遍應用到各個行業,客戶業務快速發展,傳統百人或千人上限的羣聊已經沒法知足不少業務發展需求,所以網易雲信IM推出萬人羣服務。
萬人羣場景須要解決如下問題:
1)消息須要按1:9999的比例進行轉發投遞,按常規消息處理流程將產生大量的子任務,對系統吞吐量的要求極高;
2)在微服務系統架構下,若是不採用一些優化方案,服務以及存儲(DB、緩存等)之間的QPS和網絡流量將很是高;
3)以羣爲單位的緩存(如羣成員列表)內存存儲開銷較大(假設一個成員200Byte,萬人羣約2MB);
4)羣成員登陸後須要同步羣離線消息,智能手機上App先後臺切換產生的較多登陸同步消息協議,所以須要優化消息同步方案。
爲了解決以上問題,萬人羣技術方案採用了「聚合+分層/組+增量」的設計思路:
1)按羣維護在線羣成員信息,主要包含兩部分(能夠理解爲兩個緩存集合):
a. 羣成員在線信息:即用戶在線狀態變化(上線、下線)時,更新相應羣的在線狀態信息(即動態維護羣有哪些成員在線);
b. 成員IM長鏈接信息:即用戶新登陸時,更新用戶的Link信息(即登陸所在Link的地址信息,消息轉發時根據Link地址路由消息)。
2)IM Server收到羣消息後,按羣ID將消息路由到「羣消息服務」模塊;
3)羣消息模塊檢查並預處理消息內容,而後經過「羣成員在線狀態」服務獲取在線成員,完成消息轉發的基礎工做。爲了減小羣消息模塊和羣在線成員服務之間的網絡流量,採用了「本地緩存+增量同步」的緩存策略,即本地緩存記錄最後更新版本號和時間戳,每次同步羣在線成員前先檢查緩存版本號是否有變動,如有則按最後更新時間增量同步;
4)經過「羣成員在線服務」獲取在線羣成員的Link連接信息,按Link分組路由消息(分組路由的緣由:同一Link上的所有羣成員只須要路由一條消息便可)。一樣爲了減小網絡開銷,成員Link信息也採用「本地緩存+增量同步」的方案;
5)羣消息採用「漫遊+歷史」的存儲方案,漫遊的消息存儲在分佈式緩存中,歷史消息異步寫入HBase。用戶登陸後能夠經過漫遊快速的獲取到最新消息,並能夠經過拉取歷史查看更早的消息。
拋開羣在線狀態管理邏輯,羣成員在線狀態服務能夠簡單理解爲分佈式集中緩存。
增量同步技術方案以下:
如上圖所示:
1)數據緩存是一個集合,其包含了多個緩存數據項,每個數據項帶有最後更新時間信息;另外緩存還有一個嚴格遞增的版本號;
2)緩存數據變動(新增、修改、刪除)後,須要增長版本號;
3)本地線程經過緩存管理讀取數據時,管理服務先檢查本地版本號和分佈式緩存中的版本號是否一致,若不一致則按本地最新時間戳增量同步新數據項,並更新本地的版本號和最後更新時間(爲了不分佈式集中緩存中併發寫入致使的增量時間戳不可靠問題,增量更新時能夠將本地記錄的最後更新時間戳向前推移,好比減小20ms);
4)爲避免本地多線程併發讀取相同數據項致使併發更新本地緩存的問題,能夠按緩存數據合併更新請求,即解決併發問題還能夠減小網絡開銷;
5)緩存數據由大量數據項構成,爲了不單個緩存數據太大,能夠將數據項中的屬性業務場景精簡(冷熱分離),低頻次讀寫的屬性額外緩存。
萬人羣採用大量本地緩存的方案解決消息處理性能和網絡流量的問題,所以本地存儲空間成了方案的瓶頸點。所以咱們設計了分組路由的技術方案。
消息按羣ID和路由策略定向路由到指定分組(集羣)上處理,分組由多個計算節點組成,所以方案上能夠作到分組內和分組間的水平擴縮容。
因爲萬人羣對計算和存儲資源消耗比較高,在實施和運維方案上也有必定的特殊性,爲了保證業務的可靠性和穩定性,網易雲信是將萬人大羣的能力,僅提供給專屬的雲客戶(普通公有云客戶是沒法使用的)。
之因此能從軟硬件基礎設施上爲萬人羣提供保障,網易雲信的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)