分享利用 redis 訂閱與發佈特性,巧妙的現實高性能im系統。爲表誠意,先貼源碼地址:https://github.com/2881099/im前端
下載源碼後的運行方法:ios
運行環境:.NETCore 2.1 + redis-server 2.8git
下載Redis-x64-2.8.2402.zip,點擊 start.bat 運行;或者修改 imServer、web 下面 appsettings.json redis 配置,指向可用的redis-servergithub
cd imServer && dotnet run --urls="http://0.0.0.0:6001"web
cd web && dotnet run --urls="http://0.0.0.0:5555"redis
打開多個瀏覽器,訪問 http://127.0.0.1:5555 發送羣消息算法
最二的辦法是瀏覽器端使用websocket,其餘端socket,這麼混亂的設計最終將很是難維護。json
因此強烈建議全部端都使用websocket協議,adorid/ios/h5/小程序所有支持websocket客戶端。小程序
im系統通常涉及【個人好友】、【個人羣】、【歷史消息】等等。。後端
那麼,imServer與業務方(web)該保持何種關係呢?
用戶A向好友B發送消息,分析一下:
諸如此類業務判斷會很複雜,咱們試想一下,若是使用imServer作業務協議,它是否是會變成巨無霸難以維護。
又假如獲取歷史記錄,難道客戶端要先websocket.send('gethistory'),再在onmessage裏定位回調處理?
這樣作十分之二。。。
咱這樣設計,全部用戶的主動行爲走業務方(web),imServer只負責即時消息推送。什麼意思?
用戶A向好友B發送消息:客戶端請求業務方(web)接口,由業務方(web)後端向imServer發起推送請求,imServer收到指令後,向前端用戶B的websocket發送數據,用戶B收到了消息。
獲取歷史消息:客戶端請求業務方(web)接口,返回json(歷史消息)
回執:用戶A如何知道消息發送狀態(成功或失敗或不在線)?imServer端向用戶B發送消息時,把狀態以消息的方式推給用戶A便可(按上面的邏輯),具體請看源碼吧。。。
採用消息隊列,redis的發佈訂閱最爲輕量。
單個imServer實例支持多少websocket鏈接,幾百個沒問題吧,好。。。
若是系統在線用戶有1萬人,怎麼辦???
能夠根據id的hash分區,好比部署4個imServer:
業務方(web)端根據接收方的id的hash分區算法,定位到對應的redisChannel,這樣publish就能夠將消息定位到相應的imServer了