IM系統設計
即時通訊(Instant Messaging,簡稱IM)是一個實時通信系統,允許兩人或多人使用網路實時的傳遞文字消息、文件、語音與視頻交流。實現方式有兩種。第一種基於Server轉發的,Client雙方通信會經過Server轉發來完成消息傳遞。例如QQ、微信。
第二種是基於P2P(點對點)的。P2P的實現依賴於客戶端之間的互聯,但由於NAT與防火牆的存在,客戶端無法直接互聯,需要coturn伺服器用來穿越NAT網路。
本文主要講述基於Server轉發實現的即時通訊原理和實現過程,包括私聊和群聊兩類。私聊和群聊,原理基本類似,但私聊是單次轉發,群聊屬於遍歷轉發。不同點為,群聊以群ID(多人)劃分,私聊以會話ID(兩人)劃分,其次消息存儲上也有較大差異。
總體設計
實現方式
- 協議:WebSocket
- 框架:Socket IO/Swoole
- 關鍵點:可擴展,支持分散式部署。短鏈接負責業務邏輯,長鏈接負責Websocket。
總體架構圖
時序圖詳細實現
接入層實現
接入層的目的:1保證IM服務的可靠性,避免用戶同時集中在同一聊天伺服器中。2當聊天伺服器壓力過大時,能實現擴容。接入層可採用ngx_lua實現,保證性能。
- 客戶端請求接入IM,調用接入API。參數為:接入類型(群聊,私聊),接入uid,群聊ID
- 群聊:保證隸屬同群ID的用戶落在同一Socket實例上。如果用戶ABC,都屬於群ID=123中,那麼一定要保證ABC都分配在同一實例上。具體分配策略自定,一般按照群ID取余分配在不同機器實例上。
- 私聊:A和B私聊,也要保證A和B落在同一實例上。一般分配策略為,(A+B)對機器取余。
- 根據群聊類型,得到接入實例的IP和埠,返回給客戶端。
連接邏輯
連接邏輯比較簡單,Socket connect的過程。
- 客戶端得到接入層提供的Socket Ip和埠,發起Websocket請求。
- Socket服務,根據請求參數,判斷客戶端合法性(簽名驗證)和登錄驗證。
- 記錄請求日誌,保存Socket連接句柄(當前實例數組中)。
訂閱消息邏輯
上一步連接成功後,用戶觸發進群(聊天窗口)操作,訂閱該群消息。訂閱消息用來保證,用戶通過socket實時接收到該群其他用戶發送的消息。否則,服務端會採用推送完成消息轉發。
- 訂閱事件。emit(sub),群聊:發送當前群ID和用戶的uid。私聊:發送對方uid和用戶自身uid(會話ID)。
- 服務端判斷該uid是否已經在線,如果已經在線,則主動關閉舊的Socket,保證只有當前窗口在線。並將當前socket句柄push到數組中保存。
- 業務邏輯判斷。群聊:判斷用戶是否屬於該群,判斷群合法性。私聊:判斷是否為好友。
- 客戶端在線,接收Socket消息,對消息解碼,區分類型並展示。編碼協議自定。
- 客戶端不在線,收到Push推送。客戶端根據接收到的推送,拉取歷史消息。更新未讀數。
發布消息邏輯
用戶完成訂閱群ID(群聊)或者訂閱會話ID(私聊)後,可主動發送消息到該訂閱ID(群ID和會話ID)中。
- 發布事件。emit(pub),圖片(縮略圖)、視頻、語音,完成上傳(靜態文件服務)後,編碼消息內容並提交。編碼協議自定。
- 服務端收到消息後,解碼,識別過濾色情、政治內容。寫入隊列,完成其他操作(判斷圖片色情內容,消息統計,落地入庫,更新未讀數)。
- 群聊:遍歷當前群存在的socket句柄,如果在線則轉發內容,不在線推送通知。
- 私聊:判斷對方是否在線,如果在線轉發,不在線push推送。
用戶下線
用戶退出聊天窗口,觸發disconnect事件。服務端關閉socket句柄,標示用戶下線。
廣播邏輯
廣播邏輯,主要用在運營管理上。是對所有在線用戶或者特定群ID(會話ID),發送消息(系統消息)。實現方法為:遍歷所有在線socket句柄,發送內容。
監控服務
在運營管理或者監控上,需要對聊天服務性能加以判定。 1. 統計在線人數,得到每個實例的Socket句柄長度相加
希望轉載的朋友能夠尊重作者的勞動成果,加上轉載地址。謝謝! IM系統設計
推薦閱讀: