服務(wù)端開發(fā)與架構(gòu):性能測(cè)試分析實(shí)戰(zhàn)
今天遇到一個(gè)性能壓測(cè)的問題,也是很多同學(xué)做游戲服務(wù)器開發(fā)經(jīng)常會(huì)遇到的,今天記錄一下分享給大家。
服務(wù)器硬件情況:
8核16G服務(wù)器, 帶寬1000M, redis假設(shè)在獨(dú)立的內(nèi)網(wǎng)云服務(wù)上,通過內(nèi)網(wǎng)連接;
性能壓測(cè):
壓測(cè)功能接口1: 查詢當(dāng)前服務(wù)器的時(shí)間戳,并返回給客戶端;
壓測(cè)功能接口2: 給定key, 查詢r(jià)edis服務(wù)器hash表中的一個(gè)value,并返回客戶端;
壓測(cè)手段,并發(fā)2000次請(qǐng)求;
測(cè)試功能接口1結(jié)果: (并發(fā)2000,TPS 16000,RT 20ms)
測(cè)試功能接口2結(jié)果: (并發(fā)2000,TPS 6000, RT 3000ms)
壓測(cè)問題:
為什么并發(fā)2000,查詢一個(gè)redis 結(jié)果需要等待3秒, TPS 下降到6000,哪里的問題? 如何優(yōu)化?
?
附:
RT: Response Time, 從發(fā)送請(qǐng)求到獲得結(jié)果的響應(yīng)時(shí)間,包括了Request Time, Response Time。
TPS: Transactions Per Second, 每秒處理的事務(wù)數(shù)。
遇到這類問題,我們首先要做問題分析,在處理問題之前,一定要了解清楚并發(fā)時(shí)候的服務(wù)端技術(shù)架構(gòu)組成,以及相關(guān)信息,然后再對(duì)問題做出對(duì)應(yīng)的判斷與調(diào)試。我思考了一下,先問了一些相關(guān)的問題如下:
?
問題1:?做并發(fā)測(cè)試時(shí),服務(wù)器的架構(gòu)是如何的?如何部署的?
首先就要搞清楚,當(dāng)前服務(wù)器架構(gòu)是多少個(gè)線程or進(jìn)程, 如何并發(fā)的?能否發(fā)揮多核的優(yōu)勢(shì)。
目前服務(wù)端架構(gòu)是基于Java技術(shù),網(wǎng)絡(luò)請(qǐng)求基于Java的Netty, 邏輯處理接口采用多線程來進(jìn)行處理。處理線程與Netty IO線程是分開的。目前IO線程為4個(gè),處理線程為8個(gè)。
?
問題2:?目前極限測(cè)試的情況下各CPU以及硬件設(shè)備的占比情況如何? (CPU, 內(nèi)存,IO, 網(wǎng)絡(luò)帶寬)
CPU: 目前CPU占用率約為20%;
內(nèi)存: 目前內(nèi)存的使用為1G左右, 內(nèi)存穩(wěn)定;
磁盤文件IO: 測(cè)試的時(shí)候沒有文件讀寫等IO操作;
網(wǎng)卡占用: 目前回復(fù)的都是不是大量的數(shù)據(jù),網(wǎng)絡(luò)帶寬占用很低;
?
問題3:?Redis服務(wù)器情況如何?
Redis服務(wù)器目前為獨(dú)立的,Redis服務(wù)器的資源占還很充足,目前未發(fā)現(xiàn)有太嚴(yán)重的性能問題。
?
問題4:?停掉并發(fā), 單獨(dú)響應(yīng)redis的時(shí)間未多少?是否正常?
停掉并發(fā)后,客戶端向服務(wù)端發(fā)送一個(gè)redis 查詢的請(qǐng)求,大概響應(yīng)時(shí)間為40ms左右。算上來回的網(wǎng)絡(luò)時(shí)間,是正常的。
?
問題5:?在服務(wù)器向Redis服務(wù)器做一次redis查詢多久?
這里在服務(wù)端代碼中打印,向Redis服務(wù)器查詢一次hget大約需要1ms左右。
?
為什么要問這些問題呢?這個(gè)是解決性能問題的關(guān)鍵的一些依據(jù),根據(jù)這些依據(jù)我們來制定一些問題可能的方向。問題1了解服務(wù)端基本的架構(gòu)與部署,能知道這個(gè)架構(gòu)是否能充分的發(fā)揮目前硬件的性能。問題2,主要是了解服務(wù)器是否遇到了運(yùn)行時(shí)的瓶頸,導(dǎo)致無法在提升并發(fā)性能。問題3,當(dāng)前的性能測(cè)試與Redis有關(guān)系,排除掉Redis服務(wù)器的干擾。問題4,屏蔽掉并發(fā)后,看一下整個(gè)查詢鏈路邏輯中是否有異常。排除掉一個(gè)請(qǐng)求中代碼邏輯的問題。問題5, 測(cè)試服務(wù)端請(qǐng)求Redis的情況,徹底排除掉Redis的影響,因?yàn)楸敬蔚男阅軠y(cè)試請(qǐng)求與Redis有關(guān)。
經(jīng)過上面的調(diào)查,我們總結(jié)了一下相關(guān)的情況,單次訪問Redis正常,從請(qǐng)求到返回耗時(shí)大約是40ms, 說明整個(gè)鏈路沒有大問題。
Redis查詢業(yè)務(wù)時(shí)間=客戶端發(fā)送請(qǐng)求到服務(wù)端時(shí)間+服務(wù)端查詢Redis結(jié)果的時(shí)間+服務(wù)端發(fā)送回應(yīng)到客戶端時(shí)間。
過程中沒有大規(guī)模的內(nèi)存創(chuàng)建與釋放,沒有IO操作, 內(nèi)存與IO不會(huì)為性能的瓶頸。Redis服務(wù)器一切正常,Redis支持的高并發(fā)一般不會(huì)有太大的問題。硬件的CPU占用率等都很低,并沒有發(fā)揮出來完全的硬件,說明應(yīng)該還有提升的可能。
?
假設(shè)單核情況下服務(wù)端處理業(yè)務(wù),服務(wù)端向Redis服務(wù)器請(qǐng)求需要等待1ms的話,那么2000次并發(fā)就需要2秒。同時(shí)還需要接受客戶端的請(qǐng)求+發(fā)送數(shù)據(jù)到客戶端做網(wǎng)絡(luò)IO。問題中,總共8個(gè)CPU核心,CPU占用率20%左右,和我們數(shù)據(jù)分析出來的基本能對(duì)上。從上面分析,我們可能是開的線程不夠,導(dǎo)致處理redis的時(shí)候并發(fā)率上不來,是IO線程不夠還是Task 邏輯處理線程不夠呢?從簡(jiǎn)單的查詢來推斷,應(yīng)該是邏輯處理線程不夠。IO線程處理第一個(gè)網(wǎng)絡(luò)請(qǐng)求的時(shí)候沒有問題,說明IO線程數(shù)目是沒有問題的。
?
大概估摸計(jì)算以后,我就讓小伙伴加大邏輯處理線程與IO線程,然后對(duì)比,如圖:


今天的分享就到這里了,問題比較簡(jiǎn)單,但是分析的思路值得推薦給大家,所以我就寫了這個(gè)文章。
關(guān)注我,可以獲得更多游戲開發(fā)的文章與教程。
也歡迎加入我的簡(jiǎn)介交流群