1. 程式人生 > >使用Gaps做手遊伺服器效能測試的一點心得

使用Gaps做手遊伺服器效能測試的一點心得

原文連結:

如果你想做一個很多人蔘與的遊戲,那麼無論你是專案負責人、產品、開發或者測試,伺服器效能就是你需要直面的關鍵問題。開服後大量玩家的湧入本是件好事,但若是伺服器效能出現問題,導致玩家掉線、卡頓、crash,往往樂極生悲,好事變壞事,甚至不少大作都因此落馬。

        而在遊戲開服前進行伺服器壓測,是規避伺服器事故的不二選擇。

        Gaps壓測工具(即將在WeTest上對外發布),是騰訊內部為遊戲伺服器壓測打造的專業工具,本文主要跟大家分享我在騰訊使用Gaps進行騰訊著名的天天系列手遊和騰訊代理遊戲壓測的經驗,希望對大家有所啟發和幫助。

一、編寫伺服器壓測指令碼(基於GAPS)

用gaps寫壓測指令碼主要分成三部分:網路通訊部分、遊戲業務邏輯so編寫、lua指令碼編寫控制整個壓測流程。

1、網路通訊部分

Gaps支援tcp、udp、http協議,平臺已經做了大部分的工作。對於使用者來說,只需要編寫head.so。裡面含兩個函式的編寫,GetHeaderLen()告知平臺先預收多少位元組,一般根據預收的位元組數可以分析出整個包體要收多長、GetPkgLen()明確告知平臺包體要收多長位元組,GetHeaderLen()和GetPkgLen()返回的位元組數加起來必須等於一個完整包的位元組數長度。

TCP協議:

Head.so的編寫,TCP和HTTP協議的編寫稍有差異,TCP協議,一般都在包頭中會明確的指出包長度,比如某遊戲的協議頭為:


head.so中GetHeaderLen()、及GetPkgLen()的編寫:當包位元組流來了之後,其實解析出sizeof(uint32_t)就可以分析出整個包的長度。


HTTP協議:

目前市場上游戲協議大多采用HTTP,如果HTTP包頭中含有CONTENT-LENGTH欄位的,直接配置gaps目錄下的config/ gaps_user_conf.xml即可。


如果http包頭是不含有CONTENT-LENGTH欄位的,且資料是CHUNK格式的。分下列幾種情況:

(1)http請求也分有長連線的、或是短連線的。對於短連線而言,很簡單,由於僅傳送一個請求,之後一個迴應訊息被送回來,然後TCP連線被釋放。建立一次連線收到的就是一個完整的包,Head.so的編寫很簡單。

(2)http請求是長連線的,但必須在資料流結構體中有能夠標識協議包資料長度的欄位,這樣才能分析出GetPkgLen()要具體返回多少位元組數。否則,如果既沒有CONTENT-LENGTH,又不是短連線、在預收的部分又無法解析出具體包長要收多少位元組數的,目前的GAPS平臺是不支援的。下面以一款HTTP協議遊戲的head.so編寫為例:

1、通過抓包分析,下行包的HTTP包頭的欄位資料位元組長度基本上是固定不變的。http包頭之後是具體的資料內容。那就可預估出GetHeaderLen()第一次大概收多長位元組。在後續呼叫GetHeaderLen(),可以用’\r\n\r\n’來解析。


具體的協議格式:


2、預估的GetHeaderLen()返回的長度,一定要能解析到訊息長度的位元組數。GetPkgLen()根據位元組流解析出來,然後加上chunk資料格式格外要加上的chunksize、\r\n、及最後一個0chunk標識等位元組流,就可以計算出具體需要返回的包體位元組長度了。

 


2、遊戲業務邏輯so編寫

發包流程:


收包流程:

 

3、LUA指令碼的編寫

在lua指令碼中主要是壓測場景的編寫。例如,每秒以多少人進入某個場景,按怎麼樣比例分配等。

二、定位分析伺服器效能熱點

在壓測過程中,主要關注的效能指標有:伺服器的併發事務處理能力、響應時間是否符合預期、CPU是否穩定或過高、穩定性壓測時記憶體是否洩露、磁碟讀寫繁忙程度、網路等。但最常見的是效能問題。如果出了效能問題,我們如何去分析效能熱點函式。

常見的工具中,Gprof需要重新編譯,OProfile、Perf需要核心的支援。一般地,我們較多的是選擇valgrind、和TProfile來進行分析,它們無需重新編譯即可使用。

1、TProfile的使用(結合某款鵝廠自研卡牌遊戲)

Tprofiler是由gperftools二次開發而來的伺服器效能分析工具(https://root.cern.ch/root/html/TProfile.html)。下面結合某款鵝廠自研卡牌遊戲,簡單講述下用TProfile進行分析。

1、用TProfile拉起待分析的伺服器程序後。如果伺服器程序間相互獨立,可用配置指令碼批量將程序拉起後,Kill掉待測程序,然後用TProfile重新將待測程序拉起。(呼叫start_tprofiler)

2、上機器人數量。當CPU上去後,壓測個5~10分鐘左右,即可呼叫stop_tprofiler。一定要正常關閉伺服器程序。否則無法收集到資料。

3、獲取收集的資料。在使用TProfile分析時,CPU效能分析、與堆記憶體洩露注意不要同時進行,分兩次進行採集。採集資料格式如下:


 

TProfile對待測的伺服器程序效能損耗極小(預設設定下,通常小於5%),支援多執行緒、支援動態庫函式分析。

2、Valgrind的使用(結合天美工作室旗下某款手遊)

valgrind的使用很簡單,方法如下:

1、安裝valgrind。去官網下載原始碼編譯安裝即可。

2、要測試的程式不需要重新編譯,直接用valgrind執行。


執行結束後,會自動生成名為callgrind.out.xxx的檔案,xxx是程序的pid.


3、valgrind執行程式時,程式不能以daemon的方式執行,如果執行時間很長,可以使用screen來執行。Screen的使用可以google一下,有很多資料。

4、結果分析:Valgrind的結果可以使用callgrind_annotate命令來檢視。


開啟log檔案即可檢視哪個函式耗時最多。

當初該款手遊在壓測過程中,當壓測總人數為1萬、登入併發數為每秒100人時,gamesvr伺服器程序CPU已經99+%。並且在進遊戲場景後,300人/秒、和500人/秒的併發量時,gamesvr的CPU佔用率相差近40%+。後利用Valgrind進行定位分析,主要是由於構造資料庫請求的程式碼佔了55%的處理時間。

Valgrind的優點:無需編譯程式,使用簡單,直接執行就行,支援stl,支援系統庫函式。缺點:valgrind程式本身會佔用很多的cpu,導致測試程式本身的併發量上不去。但當壓測時發現效能上不去時,可上少量的機器人,用來分析在當前測試場景下,到底哪個函式是效能熱點,已經足夠了。

三、伺服器壓測常見問題總結

在壓測專案過程中,最容易出問題的是登入場景,主要表現為TPS上不去,伺服器CPU使用率過高。對之前所做壓測專案中對它們碰到的問題、及所做的優化方法進行簡單總結下:

對某款代理遊戲登入優化的一些嘗試:

1、應用自身的登入邏輯,以及環境(Linux、JVM、Tomcat)配置。

2、用jstack看看,CPU100%的時候,看在具體哪些執行緒上面。

3、遊戲邏輯優化:

·          優化判斷邏輯。

·          對登入介面中的好友同步進行優化,不必每次登入都同步。

·          對首頁介面中的同步好友資訊,排行榜資訊等功能遮蔽,需要的時候再獲取。

·          對首頁介面中的重新計算揹包格子等功能進行遮蔽,沒有必要。

4、對tomcat引數進行優化。

5、redis連線池的優化:升級redis連線池jar包:為2.4.1,對應的commons-pool升級為commons-pool2-2.1,優化程式碼裡釋放redis連線的邏輯。

6、java程式碼優化:

·          全域性HashMap改為ConcurrentHashMap

·          迴圈中的list.size()改為先賦值給一個變數再迴圈

·          String.split改為StringTokenizer

·          通過增加各個小模組的執行時間列印,定位執行時間長的程式碼,進行優化

7、登入程式碼優化:

優化前:原來的介面是首頁介面的資料裡包括了好友資訊和排行榜資料。

優化後:現在改成了首頁資料不包括這些,只有當用戶首次進入無盡模式時,呼叫一次好友資訊和排行榜資料介面。

現在只有註冊的時候,獲取好友資訊,其他時候不是每次登入都拉好友資料的。

其他時候只有距離上次進入無盡模式介面超過5次心跳後再次進入無盡模式介面時,才會呼叫積分介面(返回好友和自己的積分)。

天天系列遊戲壓測中一些問題記錄:

1、響應超時問題、及在壓力較小情形時gamesvr的CPU佔用率高。總線上人數為3000人,每秒放500人進行遊戲請求,gamesvr的CPU為90+%;如果改為每秒放300人進行遊戲請求,gamesvr的CPU為50+%。

解決方法:由於是資料庫請求構造比較慢,構造資料庫請求程式碼佔55%的處理時間。優化時需要消除這部分事件。解決方法是加快取(tcalplus)、減少資料庫操作。

2、伺服器響應慢,還有一個原因,是訊息轉換開銷。有一個日誌配置項錯誤,導致所有進出訊息轉換成了字串,但是沒有列印到日誌。

3、共1.2w人,每秒放100人進入登入場景,部分出現響應超時、及返回系統錯誤。

解決方法:由於是有狀況沒有解鎖使用者導致返回“系統錯誤”、及排行榜的一個性能選項沒有開啟,導致隨著使用者數增加,伺服器效能下降。後調整方案後,此問題解決。

4、存在部分使用者登入返回錯誤碼-1、1(操作失敗)、35(好友關係查詢失敗)、伺服器響應超時情形。

解決方法:由於隨機會出現一些自己踢掉自己的情形,對各個服務都有影響。後加入一些保護機制,已解決該問題。

5、當“伺服器線上人數”大於“伺服器配置人數”時,如配置3000人,但測試時上線人數為4000人,伺服器未加保護策略:出了錯誤無法恢復,記憶體池用盡,且全部使用者下線30分鐘後,CPU仍舊是99+%。

解決方法:加入保護機制,當超出配置人數後,後續來的帳號登入請求,伺服器不會對其響應。

6、拉排行榜偶現錯誤碼。存在伺服器返回多個好友的OpenID是自己的。偶現最後一個好友的OPENID是空的。

解決方法:這是由於修改其他bug而導致新出現的bug。拉排行榜時候,新加了離線保護功能,做的保護還不全面,導致使用者重複登入時會出現該問題。及資料庫表的某個欄位在插入時存在問題。

7、在壓測比賽場景完後,ranksvr的CPU定期會進行抖動,CPU從<1%突然飆升到100%。主要是由於ranksvr定時更新造成。

在壓測過程中,當壓測時間比較緊時,會優先關注主流程的壓測,例如登入、拉排行、購買、戰鬥、結算等。當主流程通過後,再針對遊戲其他協議綜合壓測。根據大部分的壓測過程來看,當併發量上去後相較其他方面,資料庫方面會比較容易出問題。