壓力測試應該知道的幾個事情


1. 理解壓力測試

壓力測試的理解,xxx的性能10w/s,對你有意義么?

    沒有那家賣瓜的會說自己家的不甜,同樣,沒有哪個開源項目願意告訴你在對它條件最苛刻的時候壓力情況是多少,一般官網號稱給你看的性能指標都是在最理想環境下的,毫無參考意義。

舉個栗子,redis官網壓測的例子,256字節的讀速度11w/s,寫速度8.1w/s,都知道redis優點是多變的數據結構,string、List、hash、set、sortset,實際工作稍微復雜的環境往往都是各種結構混合使用,字符串長度各異,你需要的是真正在你的工作環境下,即:你混合使用的數據結構下,你的訪問壓力下,你的字符串長度下redis的x響應性能。這個值往往跟官方公布的差異很大。我的經驗,我們是視頻行業,相對字符串長度較長,在壓縮序列化之后,主要使用String和List,性能在訪問client=200-400左右,qps相應能到5w,超過這個client值,qps下降而且服務器負載上揚,容易引起服務器雪崩效應,這個5w,才是真正基於我們業務使用下redis的性能瓶頸。

 

我這個服務壓力2000tps,你覺得很牛逼?

       看着很牛逼對不對,好像tps值越高顯得能力越強一樣,其實很可笑,如果性能好只是比這個,那寫一個1+1=2的程序估計是無敵了吧。具體問題要具體分析,你牛逼你要說明你牛逼在哪里,在什么條件下,什么樣子的背景,才能說你的tps是多少,這樣才有意義。

 

反正線上沒出現過問題,我們撐得住,你確定?

       線上沒出現過問題,不代表流量不會增加,流量不會增加不代表業務不會復雜,業務復雜性能下降是很有可能的,沒有壓力測試做保證,出問題就是大問題。

壓力測試都是qa在做,有問題會反饋給我,你的服務極限到底在哪里?

       你應該關注一下qa是怎么做壓力測試的,無論從服務的角度還是從個人發展的角度。qa只能給你測試結果,不會告訴你性能瓶頸在哪里。

 

2.壓力測試的指標

壓測不是玩笑,你的4個9的指標呢

       好的服務都會有一項指標,叫4個9,即99.99%得服務可靠性。這是衡量一個服務是否優秀的普世標准,壓力測試的好壞最直觀的影響4個9的保障。壓力測試就是用來確保服務的穩定,給出服務穩定極限條件。穩定指的是服務負載,cpu利用率,接口的響應時長,網絡的延遲,結果准確性等等都在你的標准之內。而這些指標又相互影響。

 

條件,用盡量多的已知去推測未知,模擬仿真,你要做的預測未來

       硬件條件:服務器cpu核數、內存大小、網絡條件、同宿主機下其他服務影響,軟件條件:虛擬訪問用戶數、gc的穩定程度,響應時長要求,第三方依賴的可用程度、jdk的不同版本等都會嚴重影響壓力測試的結果,造成你的壓測結果上線之后達不到逾期。如果這些條件不注意,很可能你壓測時按照達標條件tps=1000,其實線上tps才500的時候,服務已經崩潰了。壓測的時候,最好保障壓測環境與線上一致。你的結果才更有意義。

 

3. 業務性能指標和壓力測試指標之間的差異

       tps只是結果,虛擬用戶數,線程數,平均響應時長,錯誤數,90%的平均響應時長,服務器負載,結果准確性盡量用越來越多的點來評估你的服務。

 

tps:服務處理的吞吐量,每秒響應請求的數量,tps是壓力測試最直觀的結果,是衡量服務性能的一個結果性指標,一般說壓力測試性能值就是tps值。最淺顯直白的理解,統計access日志每秒的總數就是那一秒的tps值。

 

錯誤數:一般服務壓力測試的時候是不允許出現錯誤的,即錯誤數:0%,但是復雜條件下,有的服務是允許出錯率不超過x%的,看服務而定。

 

平均響應時長:移動互聯網時代,你讓一個用戶打開app等你1s,用戶早就跑了,打開app立刻看見內容是最起碼的要求,一般好的app接口相應時間都是毫秒級別的,但是不同的場景不同的要求,我的上一家公司要求平均相應時長在20ms以內。可是上上家公司的算法接口,平均相應時長在100ms,不同的服務不同的要求,你需要找到適合你自己的要求。

 

90%的平均響應時長:jmeter學來的,表示90%的事務,服務器的響應都維持在某個值附近。比如有三個時間:1秒、5秒、12秒,則平均時間為6秒,而另外一種情況:5秒、6秒、7秒,平均時間也為6秒,顯然第二種比第一種要穩定多了。所以,我們在查看平均事務響應時間的時候,先看整體曲線走勢,如果整體趨勢比較平滑,沒有忽上忽下的波動情況,取“Average Time”與“90 Percent Time”都可以,如果整體趨勢毫無規律,波動非常大,我們就不用“Average Time”而使用“90 Percent Time”可能更真實些

 

結果准確性:多線程下訪問下結果的正確性。這個在壓測的時候往往容易被忽略。這個需要你在壓力測試的時候抽查訪問接口,查看結果是否正確,曾經碰到過qa測試通過的接口,上線之后發現返回結果不正確,內網回測正確,后來內網壓力測試的時候成功復現,是由於使用了不安全的多線程代碼導致的,其實壓測的時候抽查看一眼,很容易看出來。

 

線程數:這個指標不在各大壓力測試工具監控之內,但是這其實是壓力測試非常重要的服務指標。根據經驗,好多時候服務崩掉的時候,線程數已經滿了,好多時候應用服務器的線程在某個范圍之內,服務是最健康的狀態,超過某個范圍,服務處於不穩定狀態,處於有點網絡抖動延遲都容易崩潰的臨界點,所以熟悉這個值,你就心里清楚你的服務當前在什么狀態下。

 

 

虛擬用戶數(並發線程數):好多人容易把tps和虛擬用戶數搞混,虛擬用戶數表示當前正在訪問你服務的用戶數,就是說壓力測試工具啟動多少個線程來不停訪問你的接口。但是實際上,哪個用戶會像瘋狗一樣瘋狂一直不間斷的訪問的你接口,對用戶來說,訪問你的接口,點進去看內容,好久不再訪問才是常態(專業術語叫思考時間),可是這個值的大小,嚴重影響tps的值。那這個值多少合適呢?我知道的有2種做法,一種是求得tps的最大值,在壓力測試的時候虛擬用戶數不可測,那干脆不管,我就管好我服務的tps吞吐量,服務的吞吐量極限就是我的真實極限。做法就是找一個tps最高時的虛擬用戶數,記做壓力測試的虛擬用戶數指標,當然,這有個嚴重的問題,做過壓力測試的就知道,有的服務虛擬用戶很低時tps很高,但是虛擬用戶一但稍有提升,性能下降的非常快,怎么彌補這種情況呢,策略是補區間,得到最好tps的虛擬用戶之后,在這個虛擬用戶數之上加減某個值(例如30),得到3個壓力測試結果,3個壓力測試結果的趨勢作為服務的性能指標。第二種是估算,當前服務的tps是多少,用壓測工具可以得到達到當前tps的並發線程數是多少,但這個值肯定也只是一個估計值而已。

       多說一句,這個值為什么又可以不去管它:其實真正線上流量大的時候經常會有一種現象:服務直接重啟撐不起來當前流量,調整前端流量分配(部分nginx摘除重啟server等做法),慢慢啟動就可以支持起線上流量,再打開所有流量,發現server又可以支持沒問題了(ps:所以nginx有一個流量緩增的收費模塊就是干這個的),但是慢慢啟動線上流量和一次打過來線上流量,其實在同一時刻虛擬用戶數是差不多,斯以為這種現象是因為服務剛啟動時流量全打過來時需要創建的可復用復用對象和線程很多,容易造成了服務的不穩定,那么其實壓力測試時虛擬用戶數重要么?它真的是不可代替的么?其實虛擬用戶數只是用來探測服務性能的一個表現的總結而已,服務真正的健康情況其實反映在線程數,響應時長,服務器負載,性能瓶頸點(比如事務或者鎖)等等,而虛擬用戶數只是這些健康極限情況的表象總結而已。就是說,當壓力測試總結的虛擬用戶數在某一個范圍值tps達到多少,其實內在真正描述的是在這個虛擬用戶時,由於線程數是多少,負載是多少,平均相應時長是多少,線程數是多少,gc穩定程度是多少達到了tps值是多少。

 

 

4.面試總問的jvm調優到底是要干什么

       請注意,jvm調優,調的是穩定,並不能帶給你性能的大幅提升。服務穩定的重要性就不用多說了,保證服務的穩定,gc永遠會是java程序員需要考慮的不穩定因素之一。復雜和高並發下的服務,必須保證每次gc不會出現性能下降,各種性能指標不會出現波動,gc回收規律而且干凈,找到合適的jvm設置。詳細了解jvm的話請看神書《深入理解java虛擬機》。說些題外話,面試發現,jvm調優很多人都沒有經驗,有人甚至懷疑這東西真正是否有用,有的公司統一jvm的設置貫穿所有服務。其實只是沒碰到生產條件復雜的情況而已,舉個簡單例子:我曾經的公司,碰到過服務運行超過14h直接死機的問題,頭天下午壓測,第二天上午服務自動重啟了,按照當時習慣,新服務需要壓力測試滿12h,原則上我的服務通過測試,由於測試環境復雜,所有開發都可以登陸而且腳本很多,qa認為可能是有腳本誤殺了,但是當時離上線deadline時間還早,於是決定再壓力一次,成功復現,最后查看jvm發現每次fullgc之后o區總是會多一點,jmap打印內存棧發現char對象使用逐漸增大,最后撐滿內存, 最后定位到調用JNI發生內存泄露,解決了這個問題。這只是簡單的一次,在那家公司,由於服務偏算法而且流量很高,碰到過很多這種問題。還有一次,壓力測試loadrunner圖像顯示每隔一段時間的點上響應時間立刻下降,過2s又恢復正常,規律性很強,通過jstat發現頻繁生成大對象直接進入老年代,老年代很快撐大觸發full gc回收,回收時間過長造成服務暫停明顯,立刻反應到壓測的響應上。解決的辦法是調大年輕代,讓大對象可以在年輕代觸發yong gc,調整大對象在年輕代的回收頻次,盡可能保證大對象在年輕代回收,減小老年代縮短回收時間,服務果然穩定下來。當時這么調整下來會有一點性能損失,基本可以忽略不計,但是提升了服務的穩定性,這才是這次jvm調優最重要的。

 

5.常用的壓力測試工具及命令

loadrunner,jmeter,自寫jar包,tcpcopy等。

       壓力工具,大同小異,用什么都行,tcpcopy是拷貝線上流量,對於已有接口和服務做壓力測試是個神器,jmeter和loadrunner是壓力測試工具,loandrunner壓測結果更詳細可視化不過笨重收費而且需要很多客戶機,jmeter相對是平民版的loadrunner,勝在免費。之前也有由於數據需要實時從數據庫查詢,自己寫http的client,就需要輔助一些shell和awk命令統計相應指標。

       jmap,jstack,jstat,詳細的講解推薦《深入理解java虛擬機》,其實不神秘但是特別實用,jstat查看內存回收概況,實時查看各個分區的分配回收情況,jmap查看內存棧,查看內存中對象占用大小,jstack查看線程棧,死鎖,性能瓶頸,某個線程使用cpu過高導致服務整體慢等都可以通過在這些命令輔助linux命令看出來。

top,vmstat,sar,dstat,traceroute,ping,nc,netstat,tcpdump,ss等等具體請百度。

       你的服務是跑在linux系統上的,是依賴第三方服務出問題了?是受別的服務影響還是自己利用資源過高?是網絡抖動了?是網卡滿了么?是cpu性能不夠么?是寫入磁盤瓶頸了?內核數據交換頻繁?負載變高了?都需要linux命令才能看出來。

 

6.性能診斷到底難在哪里?

       收到服務報警了,怎么辦?打印的log日志都是連接不上memcache,難道是memcache的問題,手動客戶端連接memcache沒問題,難道是網絡的問題,測試網絡延遲很低,那到底怎么了?

其實服務類似於人體,有的人感冒的時候鼻子通氣嗓子疼,有的人頭疼,有的人流清涕,有的人流黃涕,對症下葯要治標治本。沒有什么統一的答案,這就體現了經驗的重要性。舉個栗子:某天晚上突然收到報警,vpn登陸發現服務還正常返回,暫時沒有報錯,但是負載明顯升高,resin線程數飆升到1000多(正常情況下該服務高峰期線程數500-700),cpu使用率偏高,排查:1.訪問量激增?統計發現並沒有。2.網絡狀況異常?通過訪問服務器發現也沒有,稍微慢些是因為負載稍高。3.程序有瓶頸?打印內存棧線程棧都沒發現4.受其他同宿主服務影響?查看監控發現並沒有。仔細觀察發現流量稍有波動但是不明顯。為什么負載高呢?最后排查發現是前端nginx帶寬滿了,帶寬擁堵造成代理的后端服務無法及時返回數據,后端服務的句柄數擁堵造成服務器負載升高,服務器負載升高又使線程數和cpu利用率升高,造成服務的個別訪問響應時長過長,觸發報警。再嚴重些估計就會造成連接memcache超時,log打出連接memcache錯誤的日志。蝴蝶效應而已。想要快速抓住重點,其實跟醫生一樣,就需要你對服務足夠了解,平時多關心服務狀態而且經驗真的很重要。

 

7.到底是加機器還是優化服務?

       成本,加機器是一種成本,優化服務也是一種成本,很有可能你的服務很多依賴第三方,推動他們符合你的要求也是一種溝通成本,很多時候,老板的思路永遠在於成本,如果他認為服務有很大的優化空間,那你找他加機器他多半是不會同意的,所以這種要資源的事情,請考慮成本,也有一個問題,大公司往往會哭的才有奶吃,這也很現實,反正歸根到底,對於我們這些搞服務端的來說,成就感不就應該是把硬件服務器資源壓榨到底么?

 

壓力測試你應該知道的幾個道理: https://www.iteye.com/blog/sunjia-704471770-qq-com-2282141

壓力測試TCP參數優化TIME_WAIT:  https://blog.csdn.net/a19860903/article/details/77834733

 

linux查看TCP連接數量

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM