利用 WebSocket 實現(xiàn)簡易、高性能、集群即時通訊組件,支持點對點通訊、群聊通訊、上線下線事件消息等眾多實用性功能。
Quick Start
dotnet add package ImCore
IM服務(wù)端
public void Configure(IApplicationBuilder app) { app.UseImServer(new
ImServerOptions { Redis = new
CSRedis.CSRedisClient("127.0.0.1:6379,poolsize=5"), Servers = new[] {
"127.0.0.1:6001" }, //集群配置 Server = "127.0.0.1:6001" }); }
一套永遠不需要迭代更新的IM服務(wù)端
WebApi業(yè)務(wù)端
public void Configure(IApplicationBuilder app) { //...
ImHelper.Initialization(new ImClientOptions { Redis = new
CSRedis.CSRedisClient("127.0.0.1:6379,poolsize=5"), Servers = new[] {
"127.0.0.1:6001" } }); ImHelper.EventBus( t => Console.WriteLine(t.clientId +
"上線了"), t => Console.WriteLine(t.clientId + "下線了")); }
ImHelper方法 參數(shù) 描述
PrevConnectServer (clientId, string) 在終端準(zhǔn)備連接 WebSocket 前調(diào)用
SendMessage (發(fā)送者, 接收者, 消息內(nèi)容, 是否回執(zhí)) 發(fā)送消息
GetClientListByOnline - 返回所有在線clientId
EventBus (上線委托, 離線委托) socket上線與下線事件
群聊頻道 參數(shù) 描述
JoinChan (clientId, 頻道名) 加入
LeaveChan (clientId, 頻道名) 離開
GetChanClientList (頻道名) 獲取群聊頻道所有clientId
GetChanList - 獲取所有群聊頻道和在線人數(shù)
GetChanListByClientId (clientId) 獲取用戶參與的所有群聊頻道
GetChanOnline (頻道名) 獲取群聊頻道的在線人數(shù)
SendChanMessage (clientId, 頻道名, 消息內(nèi)容) 發(fā)送群聊消息,所有在線的用戶將收到消息
說明:clientId 應(yīng)該與 webApi的用戶id相同,或者有關(guān)聯(lián)。
Html5終端
本方案支持集群分區(qū),前端連接 websocket 前,應(yīng)該先請求 webApi 獲得地址(ImHelper.PrevConnectServer)。
運行示例
運行環(huán)境:.NETCore 2.1 + redis-server 2.8
下載Redis-x64-2.8.2402.zip
<https://files.cnblogs.com/files/kellynic/Redis-x64-2.8.2402.zip>,點擊 start.bat
運行;
cd imServer && dotnet run
cd web && dotnet run
打開多個瀏覽器,訪問 http://127.0.0.1:5000 <http://127.0.0.1:5000> 發(fā)送群消息
設(shè)計思路
imServer 是 websocket 服務(wù)中心,可部署多實例,按clientId分區(qū)管理socket連接;
webApi 或其他應(yīng)用端,使用 ImHelper 調(diào)用相關(guān)方法(如:SendMessage、群聊相關(guān)方法);
消息發(fā)送利用了 redis 訂閱發(fā)布技術(shù)。每個 imServer 訂閱相應(yīng)的頻道,收到消息,指派 websocket 向終端(如瀏覽器)發(fā)送消息;
1、可緩解并發(fā)推送消息過多的問題;
2、可解決連接數(shù)過多的問題;
客戶端連接流程:client -> websocket -> imserver
imserver 訂閱消息:client <- imserver <- redis channel
推送消息流程:web1 -> sendmsg方法 -> redis channel -> imserver
imserver 充當(dāng)消息轉(zhuǎn)發(fā),及維護連接中心,代碼萬年不變不需要重啟維護;
WebSocket
比較笨的辦法是瀏覽器端使用websocket,其他端socket,這種混亂的設(shè)計非常難維護。
強烈建議所有端都使用websocket協(xié)議,websocket協(xié)議支持幾乎所有端,adorid/ios/h5/小程序全部支持websocket客戶端。
websocket用了后,就像跨平臺。。。雖然選一種語言都能連接通訊。
業(yè)務(wù)與通訊協(xié)議
im系統(tǒng)一般涉及【我的好友】、【我的群】、【歷史消息】等等。。
那么,imServer與業(yè)務(wù)方(webApi)該保持何種關(guān)系呢?
用戶A向好友B發(fā)送消息,分析一下:
* 需要判斷B是否為A好友;
* 需要判斷A是否有權(quán)限;
* 等等。。
諸如此類業(yè)務(wù)判斷會很復(fù)雜,我們試想一下,如果使用imServer做業(yè)務(wù)協(xié)議,它是不是會變成巨無霸難以維護?
又比如獲取歷史聊天記錄,難道客戶端要先websocket.send('gethistory'),再在onmessage里定位回調(diào)處理?
我們可以這樣設(shè)定,所有用戶的主動行為走業(yè)務(wù)方(webApi),imServer只負(fù)責(zé)即時消息推送。什么意思?
用戶A向好友B發(fā)送消息:客戶端請求業(yè)務(wù)方(webApi)接口,由業(yè)務(wù)方(webApi)后端向imServer發(fā)起推送請求,imServer收到指令后,向前端用戶B的websocket發(fā)送數(shù)據(jù),用戶B收到了消息。
獲取歷史消息:客戶端請求業(yè)務(wù)方(webApi)接口,返回json(歷史消息)
回執(zhí):用戶A如何知道消息發(fā)送狀態(tài)(成功或失敗或不在線)?imServer端向用戶B發(fā)送消息時,把狀態(tài)以消息的方式推給用戶A即可(按上面的邏輯),具體請看源碼吧。。。
發(fā)送消息
業(yè)務(wù)和推送分離的設(shè)計,即 imServer 只負(fù)責(zé)推送工作。
用戶A向B發(fā)消息:終端A ajax -> webApi -> imServer -> 終端B WebSocket.onmessage;
采用 redis 輕量級的訂閱發(fā)布功能,實現(xiàn)消息緩沖發(fā)送。
redis 緩沖消息發(fā)送,避免對業(yè)務(wù)方(webApi)造成消息發(fā)送的性能損耗,屬于必備,也可以更換為其他技術(shù)。
比如 webapi 業(yè)務(wù)發(fā)需要通知1000個人,不用消息緩沖的話。。。
還有使用redis存儲一些數(shù)據(jù),如在線clientId,群聊結(jié)構(gòu)。
集群分區(qū)
單個imServer實例支持多少個客戶端連接,兩千個沒問題?
如果在線用戶有10萬人,怎么辦???
比如部署4個imServer:
imServer1 訂閱 redisChanne1
imServer2 訂閱 redisChanne2
imServer3 訂閱 redisChanne3
imServer4 訂閱 redisChanne4
業(yè)務(wù)方(webApi)端根據(jù)接收方的clientId后四位16進制與節(jié)點總數(shù)取模,定位到對應(yīng)的redisChannel,進行redis->publish操作將消息定位到相應(yīng)的imServer。
每個 imServer 管理著對應(yīng)的終端連接,當(dāng)接收到 redis 訂閱消息后,向?qū)?yīng)的終端連接推送數(shù)據(jù)。
事件消息
IM 系統(tǒng)比較常用的有上線、下線,在 imServer 層才能準(zhǔn)確捕捉事件,但業(yè)務(wù)代碼就不合適在這上面編寫了。
采用 redis 發(fā)布訂閱技術(shù),將上線、下線等事件向指定頻道發(fā)布,業(yè)務(wù)方(webApi) 通過 ImHelper.EventBus 方法進行訂閱捕捉。
A向B發(fā)文件的例子
1、A向webapi傳文件
2、webapi告訴imServer,A向B正在傳文件
3、B收到消息,A正在傳文件
4、webapi文件接收完成時告訴imServer,A向B文件傳輸完畢
5、B收到消息,A文件傳輸完成(含文件鏈接)
有感而發(fā)
為什么說 signalr 不合適做 im?
im 的特點必定是長連接,輪訓(xùn)的功能用不上。
因為他是雙工通訊的設(shè)計,用hub.invoke發(fā)送命令給服務(wù)端處理業(yè)務(wù),其他就和 ajax 差不多,用來代替 ajax 減少 http 請求數(shù)量比較看好。
但是過多使用 hub,signalr
服務(wù)端會被業(yè)務(wù)入侵嚴(yán)重,業(yè)務(wù)變化頻繁后不得不重新發(fā)布版本,每次部署所有終端都會斷開連接,遇到5分鐘發(fā)一次業(yè)務(wù)補丁的時候,類似離線和上線提示好友的功能就無法實現(xiàn)。
ImCore 的設(shè)計是業(yè)務(wù)和推送分離,即 imServer 永不更新重新,業(yè)務(wù)全部在 webApi 上編寫,終端連接的是 imServer
就不會頻繁重啟的問題。
謝謝支持!
熱門工具 換一換
感谢您访问我们的网站,您可能还对以下资源感兴趣:
调教肉文小说-国产成本人片免费av-空姐av种子无码-在线观看免费午夜视频-综合久久精品激情-国产成人丝袜视频在线观看软件-大芭区三区四区无码-啊啊好爽啊啊插啊用力啊啊-wanch视频网-国产精品成人a免费观看