天天看點

鼎力推薦github 6.7k star開源IM項目OpenIM性能及消息可靠性測試

本報告主要分為兩部分,性能測試和消息可靠性測試。前者主要關注吞吐,延時,同時線上使用者等,即通常所說的性能名額。後者主要模拟真實環境(比如離線,線上,弱網)消息通道的可靠性。

先說結論,對于容量和性能:

性能及容量總結

伺服器資源: 8核16G記憶體, 6個機械磁盤,每個磁盤100G, 用于mongo分片,10MB帶寬。

容量:使用者容量10萬以上,消息條數10億條。

性能評估:同時線上使用者10萬,每秒鐘發送消息900條,消息延時1秒(從發送者發出消息到接收到消息)

可靠性總結

啟動sdk,模拟50個使用者線上、離線情況,消息可靠性100%。

發送10萬消息,有3條失敗,其他消息都能被對方精确收到,并成功落地本地db。對于失敗的3條消息,接收方确實沒有收到,系統消息是一緻的。

項目介紹

OpenIM是由前微信技術專家打造的開源的即時通訊元件。Open-IM包括IM服務端和用戶端SDK,是一套整體的解決方案,代碼開源,一切可控,

OpenIM可以實作全平台支援,目前支援Android,iOS,Flutter,Uni-app,react-native, JSSDK等。

OpenIM可以應用在企業内部辦公,dating交友,線上客服等項目,也可以用于元宇宙。

github位址:https://github.com/OpenIMSDK/Open-IM-Server

鼎力推薦github 6.7k star開源IM項目OpenIM性能及消息可靠性測試

開發者中心: https://doc.rentsoft.cn/#/

鼎力推薦github 6.7k star開源IM項目OpenIM性能及消息可靠性測試

性能測試

在單機的情況下,模拟線上使用者發消息流程,線上使用者量和消息量達到一定量級後,系統CPU、記憶體、磁盤占用、以及消息時延情況。以确定使用者群體達到一定量級後,對伺服器資源的預先評估。本次測試并不極限測試,一是因為生産環境本來都會有使用者量和消息量的限制,二是因為OpenIM的消息模型,消息發送首先都會通過websocket入庫kafka,理論上發送消息的寫入性能是兩者的組合,而消息發送的真正瓶頸實際在mongodb的随機讀寫。

測試過程

伺服器資源: 騰訊雲主機(香港)1台:linux Ubuntu 18.04.4系統,4核8G記憶體,單塊機械硬碟。5Mb帶寬。

測試條件:去掉消息入庫mysql(因mysql僅用于管理背景,不影響線上使用者服務)。日志級别調整為4或更低。kafka設定2個分區,msg_transfer 2個。

測試流程:1個用戶端(成都,window pc,4核16G記憶體)啟動1萬個協程,模拟使用者與伺服器建立websocket長連接配接,間隔時間為随機50-100秒之間。兩個用戶端共模拟2萬使用者同時線上,發送消息,觀察消息流轉各個子產品的處理能力,共計2500萬條消息,觀察系統記憶體、磁盤資源使用情況。

測試結論和分析

關注名額 測試結果
同時線上人數 20000個
網關接收消息速度 150條/s(因為瓶頸不在此,故意控制發送速度,以確定kafka能被快速消費入mongodb)
mongodb處理寫入 300條/s (收件箱模型,導緻消息一拆為二)
CPU使用率 約50%
記憶體使用率 約4G(mongo記憶體限制2G,由于每個文檔存儲5k條消息,實際實際索引量很小。 redis隻存了使用者seq映射關系,基本不占記憶體)
發送消息響應時長 平均70毫秒
發送過程時延 平約1秒
磁盤空間 mongo中5000萬條消息占用10G磁盤,由于一拆為二的緣故,mongo的50000萬條消息,實際為2500萬條消息。

mongodb資料情況

鼎力推薦github 6.7k star開源IM項目OpenIM性能及消息可靠性測試

redis資料情況

鼎力推薦github 6.7k star開源IM項目OpenIM性能及消息可靠性測試

磁盤狀态

鼎力推薦github 6.7k star開源IM項目OpenIM性能及消息可靠性測試

資源占用分析

(1)redis記憶體消耗極小,一個使用者一條資料(包括token和seq),和使用者量成正比,3萬使用者占用幾十M記憶體。

(2)mongodb如果去掉cache,記憶體消耗極小,每個document存放5000條消息,與使用者量和消息量成正比,3萬使用者,2500萬消息,索引才950K(更好的方式檢視mongo消耗cache之外的記憶體)

(3)2500萬消息,磁盤空間占用10G。

(4)每秒鐘150條消息,cpu整體占用50%,即2核。

性能分析

(1)性能瓶頸在mongodb寫入操作,1條消息,需要按照發送者和接收者拆分2次,mongodb寫入2次,未來可以針對mongodb讀寫進一步優化。

(2)對于cpu消耗較大的子產品,未來做一次整體優化。

(3)性能很平穩,不會随着資料量增加而降低。機械磁盤iops 達到200基本達到了裝置的極限

單機性能預估

伺服器資源: 8核16G記憶體, 6個磁盤,每個磁盤100G, 用于mongo分片,10MB帶寬。

子產品 性能情況 說明
msg_gateway 部署多個 ,同時線上5萬*2=10萬
mongodb 6分片,每個磁盤對應一個分片 1800條/每秒消息入庫
約100% 需要優化子產品 減少cpu消耗
小于8G(mongo記憶體限制2G) 如果記憶體富餘可以增加mongodb的cache大小
平均70ms
平約1s 從發送者到接收者
10億條消息,磁盤空間 占用40*100G磁盤,每個磁盤大概占用70G空間 對于群聊屬于擴散寫,磁盤消耗較大。整體要考慮磁盤空間富餘

未來工作優化

(1)mongo叢集部署,支援上億使用者同時線上,千億級消息;

(2)簡化叢集部署;

(3)資料備份、恢複工具;

以上主要對服務端性能做了一個大緻測試,但一套完整的IM解決方案,不僅僅是服務端的工作。實際上,用戶端重要性毋庸置疑,具體包括如何利用seq和服務端同步消息,如果保證消息收發的時序,如何回調用戶端(會話改變、新增,新消息),消息落地本地db,seq同步,消息推拉如何結合以確定消息收發可靠性。

消息可達率(可靠性)測試

相比于性能測試,實際上,消息的可達性(可靠性)更為重要。是以,我們在做性能測試的同時,也要對消息的可達性(可靠性)進行測試,如果不能保證消息收發的正确性,再高的性能也是徒勞。本文重點總結關于OpenIM對于消息可達性測試的方案、過程以及結果。先說結論,OpenIM消息可達率100%,大家可以放心使用在生産環境中。seq對齊和同步機制,保證了OpenIM的消息可達性是業界領先的。

消息可達性(可靠性)的定義

IM消息系統的可靠性,通常就是指消息投遞的可靠性,即我們經常聽到的“消息必達”,通常用消息的不丢失和不重複兩個技術名額來表示。確定消息被發送後,能被接收者收到。由于網絡環境的複雜性,以及使用者線上的不确定性,消息的可靠性(不丢失、不重複)無疑是IM系統的核心名額,也是IM系統實作中的難點之一。總體來說,IM系統的消息“可靠性”,通常就是指聊天消息投遞的可靠性(準确的說,這個“消息”是廣義的,因為還存使用者看不見的各種指令和通知,包括但不限于進群退群通知、好友添加通知等,為了友善描述,統稱“消息”)。

從消息發送者和接收者使用者行為來講,消息“可靠性”應該分為以下幾種情況:

(1)發送失敗,對于這種情況IM系統必須要感覺到,明确回報發送方。如果此消息沒有發送成功,發送方可以選擇重試或者稍後再試。

(2)發送成功,如果接收方處在“線上”狀态,應該立即收到此消息。如果接收方處在“離線”狀态不能收到消息,一旦上線則立刻收到消息。

(3)消息不能重複,用數學術語表示:“有且僅有這條消息”,如果重複了,可能表達的意思就變了。 總之,一個商用 IM系統,必須包含消息“可靠性”邏輯,才能談基本可用,這是IM系統最基本也是最核心的邏輯。

模拟場景&測試方案

網際網路真實場景複雜,但用戶端大體可以分為兩種情況:(1)發送消息時,接收方線上,能收到消息;(2)發送消息時接收方不線上,登入後能收到離線消息。我們用測試程式模拟網際網路用戶端各種場景,按照登入、發送消息、接收消息的情況,把測試用戶端分為以下2種類型:

(1)啟動測試時離線,随機sleep 0-60 秒後登入,發送消息,且接收消息

(2)啟動測試時離線,随機sleep 0-60 秒後登入,不發送消息,隻接收消息

test.ReliabilityTest(oneClientSendMsgNum, intervalSleepMs, imIP, randSleepMaxSecond, testClientNum)           

在實際測試中共計50個用戶端,約25個(50%機率)用戶端不發送隻接收消息,約25個(50%機率)用戶端發送且接收消息 。

發送模式:每個用戶端随機選擇其他用戶端作為消息接收者;

測試預期: 每一條發送成功的MsgID,都能在接收的消息清單中找到,同樣,每一條接收到的MsgID,都能在發送成功的消息清單中找到。

具體做法:(1)消息發送成功後,通過OnSuccess回調,記錄MsgID; 收到新消息後回調OnRecvNewMessage,記錄MsgID;(2)周期性對比兩個消息清單,确認是否完全一緻;

發送消息用戶端 接收消息用戶端 預設發送消息總量 發送成功條數 發送失敗條數 接收消息條數
25個 50個 100000條 99997 3

發送資料100000條,其中失敗3條,9999997條成功,接收方成功接收9999997條消息(接收方成功接收到消息,寫入本地db,并能觸發消息回調)

每一條發送成功的消息,對方都能準确接收到,無論接收方在消息發送時的登入狀态是線上還是離線。

每一條發送失敗的消息,對方都不會收到。

測試程式

main/main.go

intervalSleepMs := 1
randSleepMaxSecond := 30
imIP := "127.0.0.1"  //OpenIM ip
oneClientSendMsgNum := 4000 //每個用戶端發送的消息條數
testClientNum := 50  //同時啟動壓測用戶端數量
    
func main() {
    reliabilityTest()
}           

注意事項:

(1)控制壓力,因為sdk需要寫本地db,用戶端會成為壓力瓶頸。

(2)壓測用戶端日志會影響測試性能。

成本對比

此表格是某IM雲平台的價格,如果按照10萬月活,存儲三年消息來算,大概每年需要支付15萬。而采用OpenIM隻需要采購雲主機,每年成本約0.8萬。

鼎力推薦github 6.7k star開源IM項目OpenIM性能及消息可靠性測試
鼎力推薦github 6.7k star開源IM項目OpenIM性能及消息可靠性測試