IM系統設計

即時通訊(Instant Messaging,簡稱IM)是一個實時通信系統,允許兩人或多人使用網路實時的傳遞文字消息、文件、語音與視頻交流。實現方式有兩種。第一種基於Server轉發的,Client雙方通信會經過Server轉發來完成消息傳遞。例如QQ、微信。

第二種是基於P2P(點對點)的。P2P的實現依賴於客戶端之間的互聯,但由於NAT與防火牆的存在,客戶端無法直接互聯,需要coturn伺服器用來穿越NAT網路。

本文主要講述基於Server轉發實現的即時通訊原理和實現過程,包括私聊和群聊兩類。私聊和群聊,原理基本類似,但私聊是單次轉發,群聊屬於遍歷轉發。不同點為,群聊以群ID(多人)劃分,私聊以會話ID(兩人)劃分,其次消息存儲上也有較大差異。

總體設計

實現方式

  1. 協議:WebSocket
  2. 框架:Socket IO/Swoole
  3. 關鍵點:可擴展,支持分散式部署。短鏈接負責業務邏輯,長鏈接負責Websocket。

總體架構圖

時序圖

詳細實現

接入層實現

接入層的目的:1保證IM服務的可靠性,避免用戶同時集中在同一聊天伺服器中。2當聊天伺服器壓力過大時,能實現擴容。接入層可採用ngx_lua實現,保證性能。

  1. 客戶端請求接入IM,調用接入API。參數為:接入類型(群聊,私聊),接入uid,群聊ID
  2. 群聊:保證隸屬同群ID的用戶落在同一Socket實例上。如果用戶ABC,都屬於群ID=123中,那麼一定要保證ABC都分配在同一實例上。具體分配策略自定,一般按照群ID取余分配在不同機器實例上。
  3. 私聊:A和B私聊,也要保證A和B落在同一實例上。一般分配策略為,(A+B)對機器取余。
  4. 根據群聊類型,得到接入實例的IP和埠,返回給客戶端。

連接邏輯

連接邏輯比較簡單,Socket connect的過程。

  1. 客戶端得到接入層提供的Socket Ip和埠,發起Websocket請求。
  2. Socket服務,根據請求參數,判斷客戶端合法性(簽名驗證)和登錄驗證。
  3. 記錄請求日誌,保存Socket連接句柄(當前實例數組中)。

訂閱消息邏輯

上一步連接成功後,用戶觸發進群(聊天窗口)操作,訂閱該群消息。訂閱消息用來保證,用戶通過socket實時接收到該群其他用戶發送的消息。否則,服務端會採用推送完成消息轉發。

  1. 訂閱事件。emit(sub),群聊:發送當前群ID和用戶的uid。私聊:發送對方uid和用戶自身uid(會話ID)。
  2. 服務端判斷該uid是否已經在線,如果已經在線,則主動關閉舊的Socket,保證只有當前窗口在線。並將當前socket句柄push到數組中保存。
  3. 業務邏輯判斷。群聊:判斷用戶是否屬於該群,判斷群合法性。私聊:判斷是否為好友。
  4. 客戶端在線,接收Socket消息,對消息解碼,區分類型並展示。編碼協議自定。
  5. 客戶端不在線,收到Push推送。客戶端根據接收到的推送,拉取歷史消息。更新未讀數。

發布消息邏輯

用戶完成訂閱群ID(群聊)或者訂閱會話ID(私聊)後,可主動發送消息到該訂閱ID(群ID和會話ID)中。

  1. 發布事件。emit(pub),圖片(縮略圖)、視頻、語音,完成上傳(靜態文件服務)後,編碼消息內容並提交。編碼協議自定。
  2. 服務端收到消息後,解碼,識別過濾色情、政治內容。寫入隊列,完成其他操作(判斷圖片色情內容,消息統計,落地入庫,更新未讀數)。
  3. 群聊:遍歷當前群存在的socket句柄,如果在線則轉發內容,不在線推送通知。
  4. 私聊:判斷對方是否在線,如果在線轉發,不在線push推送。

用戶下線

用戶退出聊天窗口,觸發disconnect事件。服務端關閉socket句柄,標示用戶下線。

廣播邏輯

廣播邏輯,主要用在運營管理上。是對所有在線用戶或者特定群ID(會話ID),發送消息(系統消息)。實現方法為:遍歷所有在線socket句柄,發送內容。

監控服務

在運營管理或者監控上,需要對聊天服務性能加以判定。 1. 統計在線人數,得到每個實例的Socket句柄長度相加

希望轉載的朋友能夠尊重作者的勞動成果,加上轉載地址。謝謝! IM系統設計

推薦閱讀:

TAG:即時通訊IM | 系統設計 |