1. 程式人生 > >如何親手搭建一個分散式 IM(即時通訊) 系統

如何親手搭建一個分散式 IM(即時通訊) 系統

前言

老讀者應該還記得我之前分享過一篇《設計一個百萬級的訊息推送系統》;雖然我在文中有貼一些虛擬碼,依然有些朋友希望能直接分享一些可以執行的原始碼;這麼久了是時候把坑填上了。

目錄結構:



本文較長,高能預警;帶好瓜子板凳。





於是在之前的基礎上我完善了一些內容,先來看看這個專案的介紹吧:

CIM(CROSS-IM) 一款面向開發者的 IM(即時通訊)系統;同時提供了一些元件幫助開發者構建一款屬於自己可水平擴充套件的 IM 。

藉助 CIM 你可以實現以下需求:

  • IM 即時通訊系統。

  • 適用於 APP 的訊息推送中介軟體。

  • IOT 海量連線場景中的訊息透傳中介軟體。

完整原始碼託管在 GitHub : https://github.com/crossoverJie/cim

演示

本次主要涉及到 IM 即時通訊,所以特地錄了兩段視訊演示(群聊、私聊)。

點選下方連結可以檢視視訊版 Demo。


群聊:

私聊:

架構設計

下面來看看具體的架構設計。


  • CIM 中的各個元件均採用 SpringBoot 構建。

  • 採用 Netty+GoogleProtocolBuffer 構建底層通訊。

  • Redis 存放各個客戶端的路由資訊、賬號資訊、線上狀態等。

  • Zookeeper 用於 IM-server 服務的註冊與發現。

整體主要由以下模組組成:

cim-server

IM 服務端;用於接收 client 連線、訊息透傳、訊息推送等功能。

支援叢集部署。

cim-forward-route

訊息路由伺服器;用於處理訊息路由、訊息轉發、使用者登入、使用者下線以及一些運營工具(獲取線上使用者數等)。

cim-client

IM 客戶端;給使用者使用的訊息終端,一個命令即可啟動並向其他人發起通訊(群聊、私聊);同時內建了一些常用命令方便使用。

流程圖

整體的流程也比較簡單,流程圖如下:


  • 客戶端向 route 發起登入。

  • 登入成功從 Zookeeper 中選擇可用 IM-server 返回給客戶端,並儲存登入、路由資訊到 Redis。

  • 客戶端向 IM-server 發起長連線,成功後保持心跳。

  • 客戶端下線時通過 route 清除狀態資訊。

所以當我們自己部署時需要以下步驟:

  • 搭建基礎中介軟體 Redis、Zookeeper。

  • 部署 cim-server,這是真正的 IM 伺服器,為了滿足效能需求所以支援水平擴充套件,只需要註冊到同一個 Zookeeper 即可。

  • 部署 cim-forward-route,這是路由伺服器,所有的訊息都需要經過它。由於它是無狀態的,所以也可以利用 Nginx 代理提高可用性。

  • cim-client 真正面向用戶的客戶端;啟動之後會自動連線 IM 伺服器便可以在控制檯收發訊息了。

更多使用介紹可以參考快速啟動。

詳細設計

接下來重點看看具體的實現,比如群聊、私聊訊息如何流轉;IM 服務端負載均衡;服務如何註冊發現等等。

IM 服務端

先來看看服務端;主要是實現客戶端上下線、訊息下發等功能。

首先是服務啟動:



由於是在 SpringBoot 中搭建的,所以在應用啟動時需要啟動 Netty 服務。

從 pipline 中可以看出使用了 Protobuf 的編解碼(具體報文在客戶端中分析)。

註冊發現

需要滿足 IM 服務端的水平擴充套件需求,所以 cim-server 是需要將自身資料釋出到註冊中心的。

這裡參考之前分享的《搞定服務註冊與發現》有具體介紹。

所以在應用啟動成功後需要將自身資料註冊到 Zookeeper 中。



最主要的目的就是將當前應用的 ip+cim-server-port+http-port 註冊上去。


上圖是我在演示環境中註冊的兩個 cim-server 例項(由於在一臺伺服器,所以只是埠不同)。

這樣在客戶端(監聽這個 Zookeeper 節點)就能實時的知道目前可用的服務資訊。

登入

當客戶端請求 cim-forward-route 中的登入介面(詳見下文)做完業務驗證(就相當於日常登入其他網站一樣)之後,客戶端會向服務端發起一個長連線,如之前的流程所示:


這時客戶端會發送一個特殊報文,表明當前是登入資訊。

服務端收到後就需要將該客戶端的 userID 和當前 Channel 通道關係儲存起來。