回顧伺服器2100 2400人瓶頸

2022-09-19 09:24:11 字數 2631 閱讀 3711

經過前期的視野部分的廣播優化工作,單閘道器單邏輯服的伺服器能夠承受2100~2500人的同屏移動+釋放技能,但是在2100人之後,客戶端的ping值就會時而達到100ms以上,主觀上感到卡頓.並且到2500人時達到明顯的卡頓,遊戲無法繼續進行.這裡顯示伺服器資源在某個地方遭受到了瓶頸.

第乙個線索是ping值過高.這個ping值計算過程是 "game"->"gate"->"client"->"gate"->"game",取值上再除以2.具體哪乙個環節延遲高,需要更多的資訊.增加協議:"gate"->"game"->"gate",統計gate到game之間的訊息延遲.得到如下結果:

圖1. gategame來回延遲資料

這裡的測試結果表明,"gate""game"之間的訊息鏈存在延遲.但不能確認是哪個方向的延遲高.繼續增加協議和日誌.增加"game"->"gate"的時間戳,得到如下結果:

圖2. 增加game->gate單程延遲資料

從日誌中可以看到,兩個方向都有延遲,我們取資料量較大的乙個方向:game->gate繼續分析.這個方向的訊息處理流程如下圖:

圖3.資料鏈路示意圖,三組測試資料

圖3中下面三組資料為測試出的延遲資料分布,其"和"與上面的"單程時間"一致,測試時使用的是本地回環位址,tcp幾乎沒有消耗時間.可以看出,延遲資料主要集中在gate這邊.gate這邊的時間統計範圍具體為從"位元組流中讀拆分協議包時發現ping協議"到解析"ping協議"之間.這中間,資料只經過了recvlist.初步懷疑是recvlist資料結構的效率問題,其資料結構是concurrentqueue,是c#裡面的執行緒安全的佇列.

這裡訊息接收佇列是單生產者單消費者,訊息傳送佇列是單生產者,多消費者模型,其效率可能是瓶頸.這裡將傳送佇列修改為單生產者單消費者模型,並使用自己寫的無鎖佇列作為資料結構.修改為單生產者單消費者模型後,tcp傳送的非同步**函式來呼叫處理sendlist的傳送函式,即傳送執行緒作為乙個迴圈處理sendlist資料.這裡引起了乙個新的問題,如果傳送執行緒在無資料的時候不呼叫sleep(1ms)讓出cpu時間片,這個執行緒會持有15%左右的cpu並且不會釋放.如果有7個客戶端登入,就會佔滿了cpu.這種方式肯定不可行.如果在sendlist沒有資料的時候,呼叫sleep(1ms)讓出cpu,那麼再次喚醒就是15.625ms之後了,這樣的延遲經過多個server的跳轉之後會非常難以忍受.這種單生產者單消費者模型在windows系統上無法實施.需要修改回單生產者多消費者模型.

單生產者多消費者模型面臨多消費者競爭的時候需要正確處理,研讀concurrentqueue的進出隊**,其在面臨執行緒競爭的處理方法為自旋(spinwait),再看spinwait的**,超過20次呼叫spinwait的時候,會呼叫sleep(1ms).這個函式的實際喚起時間是大於15.625ms,因為windows的時間片為15.625ms.這似乎驗證了concurrentqueue的效率問題的猜測.需要重寫乙個適用於單生產者單消費者的佇列,其要求比concurrentqueue降低了一點,即單生產者.期望其效率能比concurrentqueue高一些.在建立測試**的時候先對concurrentqueue的進出隊的效能進行了測試.突然發現其在單生產者多消費者測試條件下的效能完全夠用.兩個消費者執行緒,每個消費者執行緒每秒取用了200多萬個資料.遠遠大於我們目前的需求,尋找瓶頸的過程走了彎路.

加入更多的時間戳日誌,經過對比發現,在原有的方式中,之所以傳送之間的時間間隔大,不是sendlist的效率不高,而是主線程呼叫傳送函式的間隔較大.繼續增加時間戳日誌,對比發現是每幀呼叫傳送函式之前,會先處理recvlist,在同屏人數較大(2000人以上)的情況下,廣播量指數增加效應明顯,gate處理廣播訊息非常耗時.導致sendlist和recvlist的訊息得不到及時處理,即延遲很高.

具體到廣播的效率問題,使用cpu分析軟體和記憶體分析得知,記憶體池的資料結構 concurrentdictionary, list>> 中的concurrentqueue在頻繁操作的時候,會產生大量記憶體交給gc,這裡存在效率問題.嘗試去掉concurrentqueue並將list修改為執行緒安全的concurrentbag,用dottrace執行結果如圖4.

圖4. 使用concurrentbag的記憶體池的測試結果

測試結果為機械人壓了1600人,就出現很大的延遲.分析圖4可以看到,concurrentbag內部的取函式操作存在著"凍結bag"、"鎖操作"等,效率較低.放棄這種方式.

經驗:尋找這種cpu分析工具無法找到的效能瓶頸,需要用日誌步步為營的進行猜測、驗證、猜測、驗證...的進行尋找,每一步的猜想和驗證都要根據現有得到的客觀結果為依據,不能亂,否則就容易走彎路.

教訓:在已經得到recvlist的延遲資料的情況下,應該繼續對recvlist進行分析,不能因為其資料結構跟sendlist同為concurrentqueue,就跳到日誌更為詳細的的sendlist進行分析,結果走了一段彎路.應該堅持步步為營.面對出現目前狀況的各種可能進行"廣度優先"去驗證,而不是"深度優先"去驗證,否則方向就容易拐到錯誤的道路上去了.

伺服器錯誤碼回顧

伺服器500錯誤。500錯誤的出現原因是很多的,但是你要知道,500錯誤是伺服器內部錯誤,而且一般程式上是asp錯誤為多的,可能是你的使用者許可權的問題導致,或者是資料庫連線出現了錯誤,那麼要好好檢查下伺服器語句錯誤問題 伺服器501錯誤。伺服器501錯誤是伺服器還是不具有請求功能的,而且501錯誤...

伺服器安裝Linux伺服器

新辦公需要搭建一台伺服器,之前也沒有怎麼搞過,不過有一些了解,於是和同事一起嘗試安裝一下伺服器。本人使用ultraiso燒錄u盤,系統檔案是centos 6.6 x86 64 bin 1.ios,使用urtraiso開啟iso檔案,然後如下圖 接著就可以寫入,u盤會被格式化的,注意備份,等待寫入就可...

mysql udp伺服器 UDP伺服器

傳輸層主要應用的協議模型有兩種,一種是tcp協議,另外一種則是udp協議。tcp協議在網路通訊中佔主導地位,絕大多數的網路通訊借助tcp協議完成資料傳輸。但udp也是網路通訊中不可或缺的重要通訊手段。相較於tcp而言,udp通訊的形式更像是發簡訊。不需要在資料傳輸之前建立 維護連線。只專心獲取資料就...