本文由冰河分享,由部落格冰河撰寫gitcode.主持人,原來的問題“如何在簡歷上寫這個分布式IM即時通訊系統?我已經幫你整理好了!本文件已經過修訂和修改。分布式IM即時通訊系統本質上是對線上聊天和使用者的管理。
對於聊天本身,核心要求是:傳送文字、檔案、語音、訊息快取、訊息儲存、訊息未讀、已讀、召回、離線訊息、歷史訊息、一對一聊天、群聊、多端同步等需求。
對於使用者管理,現有要求包括:新增好友、檢視好友列表、刪除好友、檢視好友資訊、建立群聊、加入群聊、檢視群成員資訊、退出群聊、修改群昵稱、拉人**、踢出群、解散群聊、填寫群公告、修改群備註等使用者相關需求。
為了更好地理解分布式IM即時通訊系統的設計,我站在架構師的角度,在充分了解了系統需求、業務流程和技術流程之後,從全域性的角度為系統設定了方案目標,選擇了技術方案,設計了系統的整體架構和分層架構, 並整理出發送訊息、單聊、群聊的互動鏈結。希望它有所幫助。
技術交流:
- 關於移動 IM 開發的介紹性文章:“對於初學者來說,一篇文章就足夠了:從頭開始開發移動 IM”。(本文也發表在。開源 IM 框架原始碼:備用位址單擊此處)。
在技術選型和整體架構設計之前,需要明確一件事,那就是無論系統採用哪種方案,採用哪種架構設計,都需要明確方案的業務目標、技術目標和架構目標,在研發過程中要不斷評估系統的整體效能, 並應找到系統瓶頸並不斷優化。
一般來說,我們構建和開發的分布式IM即時通訊系統需要滿足以下計畫目標。
具體說來:
業務目標:滿足需求設計章節中的各種需求場景;
技術目標:支援無限擴充套件,百萬使用者同時擴容
架構目標:高併發、高效能、高可用、監控、預警、擴充套件、無限擴充套件。
在技術選擇上,除了使用springboot等基礎框架外,還會使用容器化方案。
同時,為了盡可能降低技術門檻,整個分布式IM即時通訊系統的技術選型主要採用市面上比較流行的技術框架和解決方案。
具體選型如下:
開發框架:SpringBoot、SpringCloud、SpringCloud 阿里巴巴、Dubbo
快取:Redis分布式快取+gu**a本地快取;
資料庫:MySQL、TiDB、HBase;
流量閘道器:openresty+lua;
服務閘道器:SpringCloud Gateway + Sentinel
持久化層框架:mybatis、mybatis-plus;
服務配置、服務註冊和發現:nacos;
訊息中介軟體:rocketmq;
網路通訊:netty;
檔案儲存:minio;
日誌視覺化治理:麋鹿;
貨櫃化管理:蜂群、豬籠;
監控:Prometheus、Grafana;
前端:vue;
單元測試:junit;
基準:jmh;
壓力測試:jmeter。
對於IM即時通訊系統,涵蓋即時通訊後端服務、大型後端平台、SDK接入服務、OpenAI接入服務、大型前端UI,相信很多小夥伴或多或少都能繪製出IM即時通訊系統的架構圖,大致如下圖所示。
其實這種架構設計也是比較常見的,在這種架構設計中,Kong OpenResty NGINX 只做負載均衡和反向**,研發人員更注重業務層和基礎層的開發,流量比較小,這種架構設計一般不會有任何問題。 但是,一旦流量比較大,當使用者呼叫後端平台的介面傳送訊息時,即時通訊SDK同步呼叫即時通訊服務的介面,就會造成效能問題。
由於每個終端只能同時與乙個 IM 即時通訊服務例項建立連線,因此,如果乙個 IM 即時通訊服務恰好連線了大量使用者終端,則即時通訊 SDK 會頻繁呼叫同一 IM 即時通訊服務的介面,從而出現效能瓶頸。 在這種情況下,當效能瓶頸出現時,不僅會影響IM即時通訊服務,還會影響後端平台接收請求的業務。
既然上圖所示的架構設計存在效能瓶頸,我們該如何優化呢?
為此,我們在上圖的基礎上對架構進行了優化,優化後的架構如下圖所示。
對比兩張圖可以看出,在遮蔽技術實現細節的前提下,我們將前端對業務的驗證和流量控制,並放大 Kong OpenResty NGINX 的職責,讓這些軟體不僅具備反向**和負載均衡的功能,還實現了限速的功能, 黑白名單、流量控制、服務驗證。
也就是說,在這種架構模式下,我們充分發揮了整個分布式IM即時通訊系統的入口責任,充分利用了Kong OpenResty NGINX的高併發、高吞吐能力,並嘗試攔截了整個系統的大部分無效請求。 例如,在不登入系統的情況下,使用者嘗試呼叫傳送訊息、新增好友、新增**組等介面。 這將大大減輕後端平台的業務壓力。
除了在 Kong OpenResty NGINX 中實現限速、黑白名單、流量控制、服務驗證等功能外,我們還引入了服務閘道器集群,實現限速、降級、熔斷、流量控制、驗證、認證等功能,進一步保障下游系統的穩定性和安全性。
為了解決大量使用者終端恰好連線到同乙個 IM 即時訊息服務例項導致的效能問題,IM 即時訊息 SDK 頻繁呼叫同乙個 IM 即時訊息服務例項的介面。 我們在 IM 即時通訊服務 SDK 和 IM 即時通訊服務之間引入了乙個 RocketMQ 集群。
IM 集群中的每個 IM 例項在集群中都有乙個唯一的 ID,每個 IM 例項在啟動後只監聽 RocketMQ 中與其 ID 相關的主題。 這樣一來,每個 IM 即時通訊服務將只接收主題中與自己 ID 相關的訊息,而不會接收到所有訊息。
當使用者登入系統時,會與IM即時通訊服務建立持久連線,使用者ID和終端作為金鑰,IM即時通訊服務ID作為值,儲存在分布式快取中。 同時,將使用者ID和終端作為金鑰,以使用者終端與IM即時通訊服務之間的持久連線為值,IM即時通訊服務的本地記憶體將儲存在本地記憶體中。
當使用者呼叫後端平台介面傳送訊息時,會隨身攜帶目標使用者的ID,並在IM即時通訊SDK中指定使用者登入的終端裝置,最後通過IM即時通訊SDK將訊息傳送到RocketMQ。
這種情況下,IM SDK基於目標使用者ID和終端,從分布式快取中獲取目標使用者連線的IM即時通訊服務的ID,並向該ID相關的主題傳送訊息。 這種情況下,與目標使用者建立持久連線的 IM 即時訊息服務接收到 RocketMQ 中的訊息,然後根據使用者 ID 和終端從本地快取中獲取與使用者終端建立的持久連線,並基於持久連線向使用者推送訊息。
此外,在實際實現中,為了防止大量使用者同時只連線到IM即時通訊服務集群中的乙個服務例項,使用者會對IP、瀏覽器指紋、手機裝置等進行雜湊和模運算,使其盡可能均勻地分布到集群中的每個服務例項。
那麼問題來了,這個架構設計還有進一步優化的空間嗎?
為了進一步提公升分布式IM即時通訊系統的效能、可用性和彈性擴充套件性,我們可以設計分布式IM即時通訊系統的容器化架構,如下圖所示。
可以看出,我們進一步優化了分布式IM即時通訊系統的架構設計,採用了容器化的架構設計。 在原有架構的基礎上,我們做了如下的改進和優化。
1) 基本支援服務:基礎支援服務將通過各種基礎中介軟體、資料儲存服務、監控服務實現,包括:MySQL資料庫、Tidb資料庫、HBase、Redis快取、RocketMQ訊息佇列、Prometheus監控、Portainer容器管理等基礎中介軟體實現,基礎支援服務將為整個分布式IM即時通訊系統提供最基礎的資料、傳輸、監控和容器管理服務。
2)貨櫃化:在容器化層面,它將通過 Docker、Swarm 和 Portainer 實現,其中容器化將基於 Swarm 和 Portainer 進行管理。
3)其他基本功能實現:除了上述分層架構外,對於分布式IM即時通訊系統的構建,還需要考慮異常監控、服務註冊與發現、視覺化、業務降級與資料恢復、業務速率限制、業務容災恢復、容量規劃與伸縮、全鏈路壓力測試等。
在分布式IM即時通訊系統中,無論是大型後端平台還是IM即時通訊服務,我們都會對業務層採用分層的業務架構。
在這裡,我們可以借鑑DDD的分層架構思想,將其分為四個層:顯示層、應用層、領域層和基礎設施層。
但是,考慮到分布式IM即時通訊系統的特殊性,不會嚴格按照DDD的原則進行設計,如下圖所示。
可以看出,分布式IM即時通訊系統會借鑑DDD的設計思想,但不會完全按照DDD的方式進行設計。
1)顯示層:表示層,也稱為使用者UI層,是DDD設計的頂層,提供API介面,接收客戶端請求,解析引數,返回結果資料,處理異常。
2)應用層:應用層又稱應用層,主要處理容易發生變化的業務場景,可以處理相關事件、排程等聚合操作。
3) 域層:領域層,又稱領域層,可以說是DDD設計的本質,就是將業務系統中相對不變的部分抽象出來,封裝成乙個領域模型。 在分布式IM即時通訊系統的設計中,域層基本不依賴於其他層,也不依賴於基礎設施層,這與DDD設計不同。
4)基礎設施層:基礎結構層(也稱為基礎結構層)為其他層提供通用的基本功能,包括分布式 IM 即時訊息系統中的快取、常規實用程式類、訊息和系統永續性機制。
在分布式IM即時通訊系統中,我們忽略了其他一些細節,而把重點放在了傳送訊息的互動鏈結邏輯上。 無論是單聊還是群聊,都需要通過IM即時通訊服務將訊息推送到使用者的終端。 此時傳送訊息的流程如下圖所示。
可以看出:當使用者在分布式IM即時通訊系統中傳送訊息時,無論是單聊還是群聊,最終的訊息都會被推送到使用者登入的終端裝置。 假設使用者 A 向使用者 B 傳送訊息,或者使用者 A 和使用者 B 在同乙個組,使用者 A 向該組傳送訊息,則使用者 B 接收訊息的主要流程如下:
具體說來:
使用者 A 呼叫後端平台的 API 向使用者 B 傳送訊息,訊息中會包含使用者 B 的 ID 和終端資訊
後端平台快取訊息並將其非同步寫入訊息庫
後端平台從REDIS獲取使用者B連線的IM即時通訊服務的ID
後端平台獲取到使用者 B 連線的 IM 訊息服務 ID 後,向 RocketMQ 中使用者 B 連線的 IM 訊息服務 ID 對應的 topic 傳送訊息
IM 即時通訊服務監聽 RocketMQ 中與其服務 ID 對應的主題的訊息,使用者 B 連線的 IM 即時通訊服務接收到該訊息
IM即時通訊服務收到訊息後,會根據使用者B的ID和終端資訊,從快取中獲取使用者B與IM即時通訊服務之間的連線,並通過該連線將訊息推送給使用者B。
為了實現上述傳送訊息的過程,必須滿足以下條件:
後端平台滿足分發條件,可隨時橫向擴充套件
IM即時通訊服務滿足分發條件,可隨時橫向擴充套件
每個啟動的 IM 即時訊息服務例項在群集中都有乙個唯一的 ID
每個 IM 服務只監聽 RocketMQ 中與其 ID 對應的主題的訊息
使用者登入分布式IM即時通訊系統後,會與IM即時通訊服務建立持久連線,根據使用者ID和使用者所在終端快取持久連線,根據使用者ID及其所在終端快取已連線的IM即時通訊服務的ID到Redis中
使用者傳送訊息時,會根據目標使用者的 ID 和終端從 Redis 獲取 IM 即時訊息服務 ID,然後向當前 IM 即時訊息服務 ID 對應的 RocketMQ 主題傳送訊息
對應的 IM 即時訊息服務監聽並接收到 RocketMQ 訊息後,會根據使用者的 ID 和終端,從快取中獲取使用者的連線資訊,並將訊息推送給使用者。
一對一聊天是分布式IM即時通訊系統中使用者與另乙個使用者之間的一對一聊天。 在這種情況下,很有可能在單獨聊天的兩個使用者中,該使用者不是**。
例如:當使用者 A 向使用者 B 傳送訊息時,使用者 B 可能不會 **。
此時,我們需要儲存使用者 A 傳送給使用者 B 的訊息。
事實上,在分布式IM即時通訊系統中,我們意識到,無論使用者B是否**,訊息記錄都會被儲存。 當使用者B登入系統時,訊息會同步到使用者B,如下圖所示。
如您所見,當使用者 A 向使用者 B 傳送訊息時:
如果是使用者 b**,則可以根據傳送訊息的互動鏈結向使用者 b 傳送訊息
如果使用者 B 沒有 **,則無法正常向使用者 B 推送訊息。 使用者 B 登入分布式 IM 即時通訊系統時,會呼叫後端平台的介面拉取所有未讀訊息,並通過使用者 B ** 程序將訊息推送給使用者 B。
群聊是一種分布式IM即時通訊系統,其中多個使用者在同一群中聊天。
這時,在傳送訊息時,我們可以通過群ID找出群內所有使用者,並立即將訊息傳送給群內使用者。
那些沒有**的使用者將被視為在單次聊天中沒有**的使用者,如下圖所示。
如您所見,群聊的互動式鏈結流程如下:
使用者呼叫後端平台介面向群組傳送訊息
後端平台快取訊息並將其非同步寫入訊息庫
由於您正在向組傳送訊息,並且該組中有多個使用者,因此您將從 Redis 獲得連線到所有使用者的 IM 即時訊息服務 ID 列表
使用者按照服務ID分組,同一服務ID下的使用者分組在同乙個邏輯組中,方便後續推送訊息,沒有**的使用者列表會被記錄下來
訊息迴圈傳送到 RocketMQ 中每個服務 ID 對應的主題
廣播處理未讀使用者的未讀訊息 ID **
IM 即時訊息服務監聽自己服務 ID 對應的主題,隨時接收推送到自己服務的訊息
當 IM 即時訊息服務收到訊息時,使用者斷開連線,或者使用者沒有**,向使用者推送訊息將失敗,或者無法查詢使用者與 IM 即時訊息服務之間的連線,並且不會向使用者推送訊息
當使用者登入分布式IM即時通訊系統時,會從後端平台拉取歷史(離線)訊息,通過使用者的程序將訊息推送給使用者
那麼,看到這裡,你明白如何設計乙個高度可擴充套件的分布式IM即時通訊系統了嗎?
1] *IM系統的架構設計。
2] 簡要描述移動 IM 開發的陷阱:架構設計、通訊協議和客戶端。
3] 一套移動IM架構設計實踐分享(含細節**)海量使用者
4] 一套獨創的分布式即時通訊(IM)系統理論架構方案。
5] 如何保證移動IM中大規模群訊息推送的效率和實時性?
6] 一套面向億使用者的IM架構技術(上):整體架構、業務拆分等。
7】一套面向億使用者的IM架構技術乾貨(第二部分):可靠性、有序性、弱網優化等。
8] 從新手到專家:如何設計乙個擁有數億條訊息的分布式 IM 系統。
9] 企業微信的IM架構設計揭秘:訊息模型、萬人、已讀回執、訊息撤回等。
10] 融雲科技分享:全面揭開億級IM訊息可靠傳遞機制。
11] 阿里IM技術分享(3):仙宇億級IM訊息系統的架構演進。
12] 基於實踐:總結了具有百萬訊息量的小型 IM 系統的技術要點。
13] 從原始碼學習 IM (10):基於 Netty 構建高效能 IM 集群(含技術思路 + 原始碼)
14] 一套10萬級TPS IM整合訊息系統的架構實踐與思考。
15] 自主研發的客服IM系統從0到1的技術實踐。
16] 面向海量使用者的IM聊天室的架構設計與實踐。
17]史上最火的netty入門長文:基礎介紹、環境建設、動手實踐。
18] 初學者介紹:迄今為止對 Netty 的高效能原則和框架架構進行了最徹底的分析。
19] 對於初學者:高效能蔚來框架Netty的習方法和高階策略。
20] 教你如何使用Netty實現網路通訊程式的心跳機制和斷線重連機制。
21] 史上最強的 J**a Nio:如果你擔心開始和放棄,請閱讀這篇文章!
(本文也發表在。