golang寫的即時通訊伺服器

Alber發表於2018-11-12

1 簡要介紹

goim是一個簡單的即時通訊伺服器,程式碼全部使用golang完成,功能包含好友之間一對一聊談,群組聊天,支援單使用者多裝置同時線上,就像微信一樣,當你同時使用兩個裝置登入賬號時,兩個裝置可以都可以接收到訊息,當你用一個裝置傳送訊息時,另一個裝置也能收到你傳送的訊息。目前完成了第一版,第一版不想做的太複雜龐大,但是好多細節邏輯都做了反覆的推敲,其主要目的是先作出核心功能,不考略加快取和MQ提高效能,所以還不是很完善,以後會逐漸完善。

2 所用技術

golang+mysql完成,web框架使用了gin(對gin進行了簡單的封裝),日誌框架使用了zap,當然也自己寫了一些小元件,例如TCP拆包粘包,唯一訊息id生成器,資料庫統一事務管理等。

3 專案分層設計

專案主要氛圍兩層,connect層和logic層,public包下放置了一些connect層和logic層公用的程式碼和一些基礎庫。
connect連線層,主要維護和客戶端的tcp連線,所以connect是有狀態的,connect包含了TCP拆包粘包,訊息解碼,客戶端心跳等一些邏輯。
logic邏輯層是無狀態的,主要維護訊息的轉發邏輯,以及對外提供http介面,提供一些聊天系統基本的業務功能,例如,登入,註冊,新增好友,刪除好友,建立群組,新增人到群組,群組踢人等功能

3 拆包粘包以及訊息協議

TCP拆包粘包是自己寫的一個演算法,其思想就是每次從系統緩衝讀取資料流,放置到自己實現的一個buffer中,以後拆包粘包,還是訊息解碼都是在這個buffer完成,其目的是減少記憶體拷貝,提高效能。
其中每一個TCP都遵循TLV格式(即型別,長度,值),第一部分由兩個位元組來標示資料型別,第二部分用兩個位元組來標示資料長度,第三部分則是真正要解碼的資料。
訊息協議使用Google的Protocol Buffers,具體訊息協議定製在/public/proto包下

4 訊息唯一id

唯一訊息id的主要作用是用來標示一次訊息傳送的完整流程,訊息傳送->訊息投遞->訊息投遞迴執,用來線上排查線上問題。
每一個訊息有唯一的訊息的id,由於訊息傳送頻率比較高,所以效能就很重要,當時沒有找到合適第三方庫,所以就自己實現了一個,原理就是,每次從資料庫中拿一個資料段,用完了再去資料庫拿,當用完之後去從資料庫拿的時候,會有一小會的阻塞,為了解決這個問題,就做成了非同步的,就是保證記憶體中有n個可用的id,當id消耗掉小於n個時,就從資料庫獲取生成,當達到n個時,goroutine阻塞等待id被消耗,如此往復。

5 主要邏輯

client: 客戶端
connect:連線層
logic:邏輯層
mysql:儲存層

登入

3496be2f9ee9d33e.jpg

單發

00d7e21cccc9050e.jpg

群發

7ee3ada2baf1dec0.jpg

6 日誌

使用了zap的日誌框架,下圖展示了一次兩個裝置從登入,發一條訊息,再到下線的一次流程的完整日誌 9f644dcd04b20287.jpg

7 api文件

https://documenter.getpostman.com/view/4164957/RzZ4q2hJ

8 github

https://github.com/alberliu/goim

相關文章