goim的業務集成(分享會小結與QA)

goim 文章系列(共6篇):前端

[簡述] goim.io 是 很是成功的 IM (Instance Message) 即時消息平臺 , 本文彙總在 go夜讀 組織的 goim 交流分享會後的小結java

goim 交流分享會的視頻, 第一次用視頻會議, 一堆問題, 請包容一下 :(c++

視頻地址在 youtube www.youtube.com/watch?v=bFn…git

1. goim的系統集成與拓展

下面畫出 goim 定製擴展, 或優化的一個可行方式github

  1. 新增 AAA/LB 與 user management sub-system (UMS) , 支持用戶註冊/激活/權限等相關管理 , 尤爲是 AAA 須要支持用戶登陸認證成功後, 向用戶返回如下數據
    1. goim 須要的 json 格式 token, 指明當前用戶能夠進入哪一個 room , 能夠接收哪一個 room 的下發消息
    2. 返回 goim 的 comet 地址( 進入 room 接收 im 消息) , 以及 logic 地址 ( 發送 im 消息)
  2. 擴展 session server 會話管理, 增長用戶上下線狀態, 以支持離線消息
  3. 在 logic 上或 comet 上擴展, 增長消息存儲及相關管理, 保留服務端羣發消息( 廣播或組播), 支持聊天機器人, 增長即時消息存儲或處理接口, 好比離線消息存儲, 用戶上線後獲取離線消息(後臺觸發發送)
  4. 增長 room 管理, 開 im room 聊天室, 切換聊天室, 聊天室內的人員管理/羣主(管理員等)
  5. 在 comet 上定製擴展, client 端增長消息發送, 可雙向流式發送/接收即時消息

2. 認證集成

2.1 與 goim 交互前(登陸驗證及LB分流)

goim 客戶端, 或叫 goim 終端, 在與 goim 交互前, 應該與 AAA 或相似網元進行交互:golang

  1. 經過用戶/密碼或相關信息進行登陸, 獲取當前用戶 ID 及相關認證信息, 參見下一小節的 token
  2. AAA 返回給 goim 終端必要的路由數據, 好比當前 goim 應該去訪問哪個 comet ( 接收 im 消息) , 以及哪一個 logic ( 發送 im 消息) , 或者給 goim 終端一個 discovery 地址, 讓 goim 終端去 discovery 獲得 comet / logic 地址 -------------> 這一步算是 load balance 負載均衡吧

2.2 認證token

如下代碼取自 /examples/goim-web/public/client.jsweb

function auth() {
     var token = '{"mid":123, "room_id":"live://1000", "platform":"web", "accepts":[1000,1001,1002]}'
     
     # 參見 /api/comet/grpc/prototol.go 
     # 參見 func (p *Proto) WriteTo(b *xbytes.Writer)
     
     var headerBuf = new ArrayBuffer(rawHeaderLen);
     var headerView = new DataView(headerBuf, 0);
     var bodyBuf = textEncoder.encode(token);
     
     headerView.setInt32(packetOffset, rawHeaderLen + bodyBuf.byteLength);
     headerView.setInt16(headerOffset, rawHeaderLen);
     headerView.setInt16(verOffset, 1);
     headerView.setInt32(opOffset, 7);
     headerView.setInt32(seqOffset, 1);
     
     ws.send(mergeArrayBuffer(headerBuf, bodyBuf));

     ....
   }
複製代碼

可見 goim 進行 websocket 鏈接時, 上報了 token, 以下redis

{
  "mid": 123,                 ## memberID, 便是當前 goim 會員ID
  "room_id": "live://1000",   ## goim 會員進入的房間號, 聊天室號, 羣號
  "platform": "web",          ## goim 終端類型
  "accepts": [                ## goim 終端用戶可接受哪些 room 的 im 消息
    1000,                     ## goim 用戶切換 room, 也就在這裏處理啦
    1001,
    1002
  ]
}
複製代碼

2.3 認證的集成

認證的集成處理有兩處json

  1. 用戶在 goim 鏈接 comet 前, 應得到用戶信息, 以便構造 goim 的認證 token , 就是上章節提到的 mid / room_id / accepts 這些數據
  2. 在 logic 中處理認證, 在 /internal/logic/conn.go 中的 func (l *Logic) Connect(c context.Context, server, cookie string, token []byte) 函數體內, 處理鏈接認證的驗證, 好比檢查 mid 是否存在, 相應的 room_id / accepts 是否有權限進入等, 若是驗證經過, 則生成會話數據, 存入 redis 中; 不然返回認證失敗 ( 在 comet 中認證失敗的處理是關閉 goim 與 comet 的長鏈接 )

3. im消息發送與處理

im 消息處理, 包括如下後端

  1. 消息的存儲
  2. 消息的交互處理, 例如聊天機器人, 敏感消息過濾( 社*主義特點)
  3. 離線消息的處理
  4. 消息發送的 QOS
  5. goim 客戶端經過 comet 上行發送

4. QA

  1. 什麼是 comet

comet 【計】:基於 HTTP長鏈接的「服務器推」技術,是一種新的 Web 應用架構

基於這種架構開發的應用中,服務器端會主動以異步的方式向客戶端程序推送數據,而不須要客戶端顯式的發出請求。Comet 架構很是適合事件驅動的 Web 應用,以及對交互性和實時性要求很強的應用,如股票交易行情分析、聊天室和 Web 版在線遊戲等。

服務器推送技術(Server Push)是最近Web技術中最熱門的一個流行術語,它的別名叫Comet(彗星)。它是繼AJAX以後又一個倍受追捧的Web技術。服務器推送技術與最近的流行與AJAX有着密切的關係。 ------------百度百科

我我的也挺喜歡用 comet 這個名詞, B格不錯, 哈哈, 在個人電信相關解決方案, 這詞用來取代 adapter / gateway 這兩個比較常見的詞 , 來表明後端服務與終端的交互鏈接點, 通常是部署在 proxy 或 load balance 後面, 面向終端/客戶端提供接口服務的"後端的前端", 呵呵

  1. 關於 kafka / rabbitMQ / activeMQ / palsar / nsq / nats 等MQ的選擇

在 goim, 默認的 MQ 採用 kafka, 這是 java實現, 有衆多成功的大規模大部署長期運做商用案例的一款重量級 MQ 消息隊列

新起之秀是 palsar (java 實現) , 看技術白皮書, 很是不錯, 是比肩 kafka 的重量級做品, 但我沒用過

activeMQ 評估比較過, 在個人評估報告中,是不推薦

rabbitMQ 用過, MQ 消息中轉效率不是特別高, 也比較穩定

nsq c++ 實現, 比較低層, 效率高但不少 mq 相關業務代碼得本身寫, nsq 做者還用純c 重寫了 nsq , 叫 nano

nats 是 go 實現, 輕量級, 效率極好, 缺乏消息持久化, 是我我的挺喜歡的一款, 部署方便

選擇 MQ , 我認爲除了業務功能以外, 主要仍是看運維支持狀況, 尤爲是在超大規模部署狀況下的運維與調優, MQ 與業務的集成,反而是比重很輕的考慮因素. 因此, 個人建議是, 選擇本身運維團隊/技術團隊最熟悉的 MQ , 選擇成功商用案例最多, 生態活躍的 MQ .

在 goim , 正如 B 站選擇 kafka 同樣, 應該是比較平衡的.

至於本身業務中使用哪一個 MQ , 建議就是, 讓運維優先選擇吧, 在運維支持下, 能穩定長期運行, 這點更爲重要.

  1. 關於 goim 中的 gRPC 是否是能夠換掉

是的, 能夠換掉. 對於 go , 更換成 RPCX 應該不錯,能夠選擇 TCP / KCP 甚至是 udp 這樣的底層通信協議,也能夠更換 protobuf / flatbuffers / JSON 或者自定義的 RPC 數據序列化/反序列化........

但通常來講, 不太建議更換 gRPC.

RPC 或其餘通信中間件, 更換掉 gRPC 很容易, 建議開發團隊綜合考慮, 使用本身最熟悉最擅長的 rpc 中間件. 若是沒有本身最擅長的中間件, 那就保留 gRPC 吧.

比較主流的 RPC 框架, gRPC 不是最優秀的選擇, 好比 gRPC 缺乏自帶的服務註冊/發現, 負載均衡與調度這些商用 RPC 必要的部件, 但勝在有 google 背書, 社區還算活躍,自2018到如今, 進步還

  1. 是否能夠用 goim 做爲通訊服務噐或遊戲中的通信組件

是的, 理論上是能夠的

但不太推薦這麼玩

技術選型是很複雜, 但也很簡單的事兒: 那就是充分考慮當前/未來的業務場景(包括業務運行的各個環境......) , 以及運維/運營/研發支撐這些業務的綜合成本

雖然 goim 有長鏈接, 也有不錯的部署架構, 但畢竟是一個消息發送/彈幕業務場景積累下來的技術模型, 而不是在遊戲開發, 或通訊中間件的業務/技術積累下的最優選擇

在遊戲開發領域, 我是個小白. 但遊戲開發有兩點我認爲比較重要:

  1. 各類遊戲中會話狀態數據, 以及遊戲角色之間共享甚至是相互影響的生命值, 角色在場景(好比地圖) 中的位置數據.........這些數據會在遊戲邏輯中須要同步而且快速處理, 是一大關鍵
  2. 遊戲終端與服務端之間的高效通信, 好比有名的 16ms 原則, 通信慢了, 遊戲會卡頓

goim 之於遊戲開發, 兩個地方是能夠借鑑, 一是分佈式架構, 二是通信交互中數據(對於 goim 來講是彈幕消息) 的自定義的序列化/反序列化, 以及多發消息的合併傳輸, 這很精巧有效啊... _

_

_

5. 結語

goim 系列小文章, 這一篇是終結了.

得益於喜歡開源的朋友們, 一個多月來 360度花式詢問與交流, 在閒着的時間, 寫了這些小文章.

2019/05/30晚上, 與70多位朋友以視頻會議方式就 goim 及周邊技術聊了一個半小時, 也是頗有趣的經歷: 視頻中的我, 特別像一個面對着屏幕的客服男, 哈.


再一次, 感謝 www.bilibili.com 的開源 & 毛劍 大神, 及衆多開源社區的前輩們,朋友們

關於我

網名 tsingson (三明智, 江湖人稱3爺)

原 ustarcom IPTV/OTT 事業部播控產品線技術架構溼/解決方案工程溼角色(8年), 自由職業者,

喜歡音樂(口琴,是第三/四/五屆廣東國際口琴嘉年華的主策劃人之一), 攝影與越野,

喜歡 golang 語言 (商用項目中主要用 postgres + golang )

_

_

tsingson 寫於中國深圳 小羅號口琴音樂中心, 2019/05/30, 最後更新於 2020/01/06

相關文章
相關標籤/搜索