Gobelieve 架構(轉載)

来源:https://www.cnblogs.com/nuanshou/archive/2019/03/07/10492674.html
-Advertisement-
Play Games

Gobelieve 架構 Gobelieve github地址 im 客戶連接伺服器 (可分散式部署,暫無負載均衡模塊) imr 路由查詢伺服器(主要解決im分散式部署的問題) ims 存儲伺服器 (主從部署) 基礎模塊 1.數據包協議 包:header(12)|body header:len(4) ...


Gobelieve 架構

Gobelieve github地址

im 客戶連接伺服器 (可分散式部署,暫無負載均衡模塊)

imr 路由查詢伺服器(主要解決im分散式部署的問題)

ims 存儲伺服器 (主從部署)

基礎模塊


1.數據包協議

包:header(12)|body

header:len(4),seq(4),cmd(1),version(1),空(2)

2.數據收發流程

accept收到一個連接
開啟寫線程和讀線程

寫線程:監聽client.wt阻塞隊列,一有數據就寫入conn

讀線程:按照數據包協議從conn讀出數據包,由client.HandleMessage處理

 

3.幾個方法

PushMessage 通過route_channel 發送 MSG_PUBLISH 給IMR
PushGroupMessage 通過route_channel 發送 MSG_PUBLISH_GROUP 給IMR
SaveMessage 通過IMS RPC服務 調用SavePeerMessage
SaveGroupMessage 通過IMS RPC服務 調用SaveGroupMessage
im_client.SendMessage
    1.PushMessage
    2.本地路由查詢 並EnqueueMessage
im_client.SendGroupMessage
    1.PushGroupMessage
    2.group_manager查詢group
    3.由group得到所有menber,對每個menber查詢路由表,並EnqueueMessage
im_client.EnqueueMessage
    將數據寫入client.wt,供發送出去

 

IM 模塊


IM模塊初始化

1.redis_pool

2.storage_pools 連接ims:3333

http伺服器讀取最近消息時調用

3.rpc_clients ims:13333

SyncMessage
SyncGroupMessage
SavePeerMessage
SaveGroupMessage

4.group_rpc_clients (可選)

5.route_channels 連接imr:4444

開啟讀寫線程
寫:從channel.wt管道取值併發送給imr
讀:從imr接受消息,並分發給當前im節點連接用戶

6.group_manager

1.load: 從mysql載入group,保存至 group_manager.groups
2.run: reids訂閱 
case group_create、
    group_disband、
    group_member_add、
    group_member_remove、
    group_upgrade、
    回調處理 增刪改查group_manager.groups
case ping
    臟數據檢測
3.ping:
   每個五分鐘發送ping

7.group_message_deliver:普通群消息分發

1.init:創建本地存儲文件
2.run: 監聽wt管道,有數據表示有新消息寫入文件
        讀取文件併發送

8.ListenRedis 禁言

redis訂閱 speak_forbidden
接受事件推送,從本地路由查詢到對應client,修改forbidden欄位。

9.SyncKeyService

從 group_sync_c 和 sync_c 管道取值,保存至redis
( 客戶端發送的 MSG_GROUP_SYNC_KEY 和 MSG_SYNC_KEY 消息會將消息內同步key寫入對應的管道 group_sync_c 和 sync_c)

10.StartHttpServer :6666

web伺服器

11.StartSocketIO :websocket

12.ListenClient :23000 處理客戶端連接

ListenClient 處理流程


1.登錄認證 cmd:MSG_AUTH_TOKEN

客戶端將uid與token傳給伺服器,由redis_pool查詢認證

認證成功: 1.由EnqueueMessage發送消息{cmd:MSG_AUTH_STATUS,status:0}
        2.client.AddClient() 緩存本連接到本機路由表
        3.client.IMClient.Login() 緩存本鏈接到IMR路由表
認證失敗: 由EnqueueMessage發送消息{cmd:MSG_AUTH_STATUS,status:1}

2.IMClient 處理消息類型

MSG_IM: 處理IM 同步消息
MSG_GROUP_IM: 處理Group 同步消息
MSG_INPUTING: 處理Inputing消息
MSG_RT: 處理實時消息
MSG_UNREAD_COUNT: 設置未讀消息數
MSG_SYNC: 客戶端請求同步最新消息
MSG_SYNC_KEY: 客戶端將SYNC_KEY 傳至服務端
MSG_SYNC_GROUP: 客戶端請求同步最新群消息
MSG_GROUP_SYNC_KEY: 客戶端將GROUP_SYNC_KEY 傳至服務端

RoomClient 消息類型

MSG_ENTER_ROOM:進入聊天室
MSG_LEAVE_ROOM:離開聊天室
MSG_ROOM_IM:聊天室IM消息

VOIPClient消息類型

MSG_VOIP_CONTROL: VOIP命令

CustomerClient消息類型

MSG_CUSTOMER: 顧客->客服
MSG_CUSTOMER_SUPPORT:客服->顧客

3.MSG_IM處理流程:
用戶A -> B

1.SaveMessage:保存消息到目標用戶B存儲隊列 (rpc->SavePeerMessage)
2.SaveMessage:保存消息到發送用戶A存儲隊列(供多點登錄同步消息)
3.PushMessage:外部推送消息給目標用戶B(由IMR尋路由)MSG_IM
4.SendMessage:發送同步消息給目標用戶B (外部推送+本地定址發送) MSG_SYNC_NOTIFY
5.SendMessage:發送同步消息給發送用戶A(多點登錄)MSG_SYNC_NOTIFY
6.EnqueueMessage:給本連接回覆MSG_ACK消息

4.MSG_GROUP_IM處理流程

1.由group_manager查詢到指定group
2.根據Group類型:
    1.HandleSuperGroupMessage:
        SaveGroupMessage:保存MSG_GROUP_IM消息 (rpc->SaveGroupMessage)
        PushGroupMessage:外部推送群消息 MSG_GROUP_IM
        SendGroupMessage:發送群同步通知消息(外部推送+本地定址推送) MSG_SYNC_GROUP_NOTIFY
    2.HandleGroupMessage:
        group_message_deliver:
            saveMessage:本地保存消息 MSG_PENDING_GROUP_MESSAGE
            ReadMessage:讀取消息 MSG_PENDING_GROUP_MESSAGE
            對群每個成員:SaveMessage:保存MSG_GROUP_IM消息 
                        PushMessage:外部推送消息 MSG_GROUP_IM
                        SendMessage:發送同步消息 MSG_SYNC_NOTIFY
3.EnqueueMessage:給本連接回覆MSG_ACK消息

5.MSG_INPUTING:

SendMessage:發送給目標用戶

6.MSG_RT 實時消息處理流程

SendMessage:發送消息給目標用戶

7.MSG_UNREAD_COUNT 設置用戶未讀數:

由redis_pool操作 hashkey:users_$appid_$uid field:unread

8.消息同步流程:

服務端->客戶端 MSG_SYNC_NOTIFY:
    客戶端:
    1.isSyncing==false:sendSync 發送舊syncKey,請求消息MSG_SYNC,狀態切換為同步狀態
    2.isSyncing==true: 同步狀態中,新的newSyncKey 保存在pendingSyncKey中,this.pendingSyncKey = newSyncKey;

客戶端->服務端:MSG_SYNC
    服務端:
    1.從客戶端傳來的sync_key得到last_id,(如果last_id==0,從redis取出最新sync_key)
    2.rpc->SyncMessage:根據last_id取出緩存的最近消息msgs
    3.EnqueueMessage:發送MSG_SYNC_BEGIN消息 (客戶端不做處理)
    4.EnqueueMessage:迴圈發送msgs
    5.EnqueueMessage:發送MSG_SYNC_END消息 其中包含sync_key為最後一條msg的MsgID

服務端->客戶端:MSG_SYNC_END
    客戶端: 
    1.取出newSyncKey(如果newSyncKey>this.syncKey,客戶端保存newSyncKey,併發送給服務端MSG_SYNC_KEY)
    2.切換同步狀態isSyncing = false; 
    3.如果this.pendingSyncKey > this.syncKey ,
        即在上次同步中有新的MSG_SYNC_NOTIFY消息傳給客戶端,則再次同步,sendSync發送syncKey,pendingSyncKey置零

客戶端->服務端: MSG_SYNC_KEY
    服務端:
    1.從sync_key得到last_id,
    2.包裹成SyncHistory,寫入管道sync_c <- s

 

  消息傳輸流程

9.超級群同步流程

服務端->客戶端 MSG_SYNC_GROUP_NOTIFY
    客戶端: 
    1.isSyncing==false:sendSync 發送舊syncKey,請求消息MSG_SYNC_GROUP,狀態切換為同步狀態
    2.isSyncing==true: 同步狀態中,新的newSyncKey 保存在pendingSyncKey中,this.pendingSyncKey = newSyncKey;

客戶端->服務端 MSG_SYNC_GROUP
    服務端: 
    1/從客戶端傳來的group_sync_key取出group_id,sync_key,last_id=sync_key,(如果last_id,從redis取出新的group_sync_key_$groupid)
    2.rpc->SyncGroupMessage:根據last_id取出最近的群消息 msgs
    3.EnqueueMessage:發送MSG_SYNC_GROUP_BEGIN 消息
    4.EnqueueMessage:迴圈發送msgs
    5.EnqueueMessage:發送MSG_SYNC_GROUP_END,其中sync_key為最後一條msg的MsgID

服務端->客戶端 MSG_SYNC_GROUP_END
    客戶端:
    1.取出GroupSyncKey.syncKey和當前syncKey(如果GroupSyncKey.syncKey較大,客戶端保存更新,併發送給服務端 MSG_GROUP_SYNC_KEY)
    
    2.切換同步狀態isSyncing = false;
        如果this.pendingSyncKey > this.syncKey ,
            即在上次同步中有新的MSG_SYNC_NOTIFY消息傳給客戶端,則再次同步,sendSync發送syncKey,pendingSyncKey置零

客戶端->服務端 MSG_GROUP_SYNC_KEY
    服務端:
    1.取出group_id last_id
    2.包裹成SyncGroupHistory,寫入管道group_sync_c <- s 

 


IMR模塊

1.redis_pool

2.group_manager

3.ListenClient :4444

1.MSG_SUBSCRIBE
2.MSG_UNSUBSCRIBE
3.MSG_SUBSCRIBE_ROOM
4.MSG_UNSUBSCRIBE_ROOM
(以上四個均是對imr維護的路由表增刪改查)
5.MSG_PUBLISH
    1.根據消息內容得到消息類型和目標用戶
    2.查詢路由表,用戶如果離線則將消息放入第三方推送隊列
    3.根據路由表得到用戶連接所在im節點,並把消息推送至該節點
    
    第三部過濾條件:
        1.消息類型不為 MSG_IM、MSG_GROUP_IM、MSG_CUSTOMER、MSG_CUSTOMER_SUPPORT、MSG_SYSTEM
        2.目標IM節點和發送IM節點不是同一節點

6.MSG_PUBLISH_GROUP
    1.根據消息內容得到消息類型和群
    2.對群內每個成員查詢路由表,用戶如果離線則將消息放入第三方推送隊列
    3.群發給所有IM節點
    
    第三部過濾條件:
        1.消息類型為 MSG_PUBLISH_GROUP

7.MSG_PUBLISH_ROOM
    1.根據消息內容得到roomid
    2.根據roomid查詢路由表得到所有節點
    3.對每個節點發送消息

    第三部過濾條件:
        1.發送節點和目標節點不是同一節點

 

  IMR架構

IMS模塊 (主從)

1.NewMaster

1.init:創建容器存儲 clients,創建隊列ewt
2.run:監聽隊列ewt,將ewt隊列內消息添加到緩存cache數組
    cache每滿1000或者每隔1分鐘,執行SendBatch,
    SendBatch:
        封裝消息 MSG_STORAGE_SYNC_MESSAGE_BATCH ,寫入每個從節點連接的消息隊列client.ewt

2.NewSlaver 監聽主節點(可選)

run:連接至主節點,連接成功發送 MSG_STORAGE_SYNC_BEGIN
    迴圈讀取消息:
        MSG_STORAGE_SYNC_MESSAGE storage.SaveSyncMessage(emsg)
        MSG_STORAGE_SYNC_MESSAGE_BATCH storage.SaveSyncMessageBatch(mb)

3.waitSignal 處理中斷 SIGINT SIGTERM

storage.FlushPeerIndex() 將每個人最近消息的msgid寫入文件
storage.FlushGroupIndex()

4.ListenSyncClient master監聽 3334

處理從節點連接 RunLoop:
    1.(初始化同步)接受 MSG_STORAGE_SYNC_BEGIN 消息,從中取得msgid,
    根據msgid LoadSyncMessagesInBackground 查詢得到消息,併發送給從節點 
    2.將從節點連接添加至 clients
    3.進入for迴圈,監聽消息隊列client.ewt併發送給從節點
    4.迴圈break後 RemoveClient

5.ListenRPCClient :13333

SyncMessage
SyncGroupMessage
SavePeerMessage
SaveGroupMessage
GetNewCount
由im調用

6.ListenClient() 3333

對於每個連接:
    1.init:創建寫管道wt
    2.run :寫線程,從wt管道取數據併發送
            讀線程,HandleMessage

7.HandleMessage

1.MSG_LOAD_OFFLINE  
    對IM: storage_client.LoadOfflineMessage響應
2.MSG_SAVE_AND_ENQUEUE 
    對IM:storage_client.SaveAndEnqueueMessage響應
3.MSG_DEQUEUE 
    對IM: storage_client.DequeueMessage響應
*4.MSG_LOAD_LATEST
    對IM-StartHttpServer-LoadLatestMessage響應
*5.MSG_LOAD_HISTORY 
    對IM-StartHttpServer-LoadHistoryMessage響應
6.MSG_SAVE_AND_ENQUEUE_GROUP  
    對IM: storage_client.SaveAndEnqueueGroupMessage響應
7.MSG_DEQUEUE_GROUP 
    對IM :storage_client.DequeueGroupMessage響應
8.MSG_LOAD_GROUP_OFFLINE 
    對IM: storage_client.LoadGroupOfflineMessage響應

(上述除了4,5,暫無被IM模塊調用)

 

IMS架構



作者:JackieF777
鏈接:https://www.jianshu.com/p/8121d6e85282
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題目 682. 棒球比賽 你現在是棒球比賽記錄員。給定一個字元串列表,每個字元串可以是以下四種類型之一:1.整數(一輪的得分):直接表示您在本輪中獲得的積分數。2. "+"(一輪的得分):表示本輪獲得的得分是前兩輪有效 回合得分的總和。3. "D"(一輪的得分):表示本輪獲得的得分是前一輪有效 回合 ...
  • Element組件網址: http://element-cn.eleme.io/#/zh-CN/component/message Layer組件網址: https://www.layui.com/doc/modules/upload.html 測試介面: 用Postman或者網址http://lo ...
  • (盜圖鎮樓) 多頁應用 每一次頁面跳轉的時候,後臺伺服器都會返回一個新的html文檔,這種類型的網站就是多頁網站,也叫多頁應用。{頁面跳轉——>返回html} 優點是:首屏時間快,seo效果好;缺點是:頁面切換慢; 為什麼多頁應用的首屏時間快? 首屏時間叫做頁面首個屏幕的內容展現時間,當我們訪問頁面 ...
  • "知乎原鏈" 本文為 "中文代碼示例之5分鐘入門TypeScript" 的 "CTS" 版本. CTS作者是@htwx(github). 它實現了關鍵詞和標準庫的所有命名漢化. 本文並未使用附帶的vscode相關插件(包括CTS語言插件和拼音輸入插件), 與原Typescript教程類似, 只用了命 ...
  • 前段時間做了微信自定義分享的功能,分享出的頁面存在邀請碼在ios手機上複製失敗的問題,然而在PC端和安卓機上是沒有問題的。百度了一下,基本給出的解決方案是:ios不單純支持on,為點擊的元素添加空點擊事件:onclick="",眾說芸芸,但是試了下沒一個有用! 如果你複製的文本內容來自是input的 ...
  • 題目 169. 求眾數 給定一個大小為 n 的數組,找到其中的眾數。眾數是指在數組中出現次數大於 ⌊ n/2 ⌋ 的元素。 你可以假設數組是非空的,並且給定的數組總是存在眾數。 示例 1: 示例 2: 眾數(Mode)是統計學名詞,在統計分佈上具有明顯集中趨勢點的數值,代表數據的一般水平(眾數可以不 ...
  • 一、什麼是橋接模式 橋接模式(Bridge Pattern):將抽象部分與它的實現部分分離,使它們都可以獨立地變化。它是一種對象結構型模式,又稱為柄體(Handle and Body)模式或介面(Interface)模式。 二、橋接模式的結構 在橋接模式結構圖中包含如下幾個角色: ●Abstract ...
  • 如果第二次看到我的文章,歡迎右側掃碼訂閱我喲~ 👉 本文長度為5389字,建議閱讀14分鐘。 堅持原創,每一篇都是用心之作~ 沒想到這篇文章寫了這麼長,一時半會沒消化完的話,可以收藏一下先。 這是「伸縮性」章節的第四篇,先給新來的小伙伴們簡單回顧下前三篇的內容。 做「伸縮性」最重要的就是先做好「無 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...