:從安裝配置、參數(shù)化斷言到非GUI壓測報告)
打從第一次接觸性能測試開始我在工具選型這件事上就沒少糾結(jié)。LoadRunner太重、商用授權(quán)貴得離譜Locust寫起來靈活但對沒多少編碼基礎(chǔ)的同事不太友好最后兜兜轉(zhuǎn)轉(zhuǎn)還是回到了JMeter。原因很簡單Apache基金會背書、純Java實現(xiàn)、跨平臺、免費(fèi)開源、插件生態(tài)成熟而且不管是接口功能測試、壓力測試還是簡單的接口自動化回歸它都能扛下來。今天我就把Jmeter的安裝、配置、中文環(huán)境、內(nèi)存調(diào)優(yōu)一直到第一個能跑起來的壓測腳本、參數(shù)化、斷言、非GUI執(zhí)行和結(jié)果報告整套流程掰開揉碎講一遍。這篇內(nèi)容面向前后端開發(fā)、測試工程師以及剛轉(zhuǎn)行做性能測試的朋友只要你會基本的上網(wǎng)操作跟著做就能落地。下面所有步驟都是我在Windows環(huán)境下親測跑通的Linux上的差異我也會補(bǔ)充說明。1. 為什么我最后選了JMeter從一次接口壓測說起1.1 那次被逼上梁山的壓測需求幾年前我還在做電商后端產(chǎn)品上線前一周運(yùn)營突然跑過來說大促期間要預(yù)估一下訂單接口的承載能力問我能不能給個QPS能到多少的結(jié)論。當(dāng)時團(tuán)隊沒有任何性能測試的積累連壓測工具都沒統(tǒng)一。我第一反應(yīng)是找LoadRunner結(jié)果發(fā)現(xiàn)license問題繞不過去。后來試了試JMeter從下載到跑出第一份報告前后不到一個下午。也就是從那次之后JMeter就成了我工具箱里的固定成員。我第一次用JMeter壓的接口很簡單就是一個下單查詢接口壓到500并發(fā)的時候服務(wù)端開始出現(xiàn)超時查下來發(fā)現(xiàn)是數(shù)據(jù)庫連接池只有20個連接線程都在排隊。這個問題如果不壓測上線后大概率會在大促當(dāng)天爆出來。所以壓測的價值從來不是跑個工具顯得專業(yè)而是在流量真正到來之前把系統(tǒng)的拐點(diǎn)找出來。1.2 JMeter的定位和能力邊界很多人對JMeter有個誤解以為它只能做HTTP壓測。實際上它的能力范圍比想象中廣得多協(xié)議支持廣泛HTTP/HTTPS、FTP、JDBC、JMS、SOAP/REST、TCP、SMTP等通過插件還能擴(kuò)展MQTT、gRPC這些。不只是壓測接口功能測試、參數(shù)化數(shù)據(jù)驅(qū)動測試、回歸測試都能做很多團(tuán)隊直接拿它當(dāng)輕量的接口自動化框架。可視化與腳本化并存既能在GUI里點(diǎn)點(diǎn)點(diǎn)配置也能用Groovy/BeanShell寫自定義邏輯靈活度足夠??蓴U(kuò)展插件機(jī)制成熟官方Plugins Manager可以一鍵裝各種擴(kuò)展比如MQTT插件、自定義監(jiān)聽器。我個人的經(jīng)驗是JMeter最舒服的場景是中大型接口的性能基線測試和長期回歸對比尤其是需要和現(xiàn)有CI流程結(jié)合的時候。它的命令行模式非GUI配合HTML報告可以很自然地塞進(jìn)Jenkins流水線里。1.3 學(xué)JMeter最容易走的彎路新手學(xué)JMeter彎路基本集中在三個地方。第一個是環(huán)境沒配好就開始跑JDK版本和JMeter版本不匹配一啟動就報錯然后開始懷疑人生。第二個是GUI模式下直接壓高并發(fā)JMeter的GUI本身很吃資源幾百個線程一起跑GUI先卡死了誤以為是服務(wù)端扛不住。第三個是不區(qū)分功能測試和壓測的腳本寫法把帶大量調(diào)試監(jiān)聽器的腳本直接拿去壓測性能數(shù)據(jù)全被監(jiān)聽器拖垮。這三點(diǎn)我會在后面分別展開講尤其是環(huán)境這一步很多人栽在JDK版本上。記住一句話JMeter本質(zhì)是個Java程序Java環(huán)境不對后面全是白搭。2. 環(huán)境準(zhǔn)備JDK與JMeter的版本搭配與安裝2.1 JDK版本到底選哪個JMeter是基于Java開發(fā)的所以必須要先有Java運(yùn)行環(huán)境。這里是第一個大坑。不同JMeter版本對JDK的最低要求是不一樣的。早期JMeter 5.0以前JDK 8就夠用。但從JMeter 5.4開始官方推薦用JDK 8以上而JMeter 5.6之后的版本我實測JDK 17跑起來體驗最穩(wěn)。表格整理一下JMeter版本推薦的JDK版本說明5.3及以前JDK 8穩(wěn)定老項目多用這個組合5.4 ~ 5.5JDK 8 / JDK 11兩者都行JDK 11更推薦5.6及以后JDK 17官方推薦性能和兼容性最好我個人的建議是如果你是新起項目直接上JDK 17 JMeter 5.6.3這個組合省心。如果你所在公司現(xiàn)有系統(tǒng)都是JDK 8那裝JDK 8 JMeter 5.4.1也沒問題兩個JDK其實可以在同一臺機(jī)器上共存用環(huán)境變量切換就行。2.2 JDK安裝與環(huán)境變量配置到Oracle官網(wǎng)或者采用OpenJDK如Adoptium Temurin下載對應(yīng)版本的JDK安裝包。安裝路徑我建議別放帶中文和空格的目錄比如D:\dev\jdk-17不然偶爾會遇到路徑解析的詭異問題。安裝完之后關(guān)鍵是配置環(huán)境變量。Windows下新建系統(tǒng)變量JAVA_HOME值為JDK安裝目錄比如D:\dev\jdk-17。編輯Path變量新增一條%JAVA_HOME%\bin。打開cmd執(zhí)行java -version能打印出版本號就說明配置成功。配置好之后命令行輸出大概是這樣java version 17.0.9 2023-10-17 LTS Java(TM) SE Runtime Environment (build 17.0.911-LTS-237) Java HotSpot(TM) 64-Bit Server VM (build 17.0.911-LTS-237, mixed mode, sharing)如果這一步報java 不是內(nèi)部或外部命令百分之九十是Path沒配好檢查一下%JAVA_HOME%\bin有沒有加進(jìn)去。這里有個小技巧Path里的順序會影響生效的JDK。如果你機(jī)器上裝了多個JDK把想要的那個bin放前面。2.3 JMeter下載與目錄結(jié)構(gòu)說明JDK搞定之后去Apache JMeter官網(wǎng)下載頁下載apache-jmeter-5.6.3.zip這個壓縮包。注意別下成源碼包帶-src后綴的源碼包解開是沒法直接跑的。解壓到任意目錄比如D:\dev\apache-jmeter-5.6.3。解開之后的目錄結(jié)構(gòu)大致是這樣目錄/文件作用bin/啟動腳本目錄jmeter.batWindows、jmeter.shLinux都在這lib/核心依賴jar包插件下載的jar也放這lib/ext/擴(kuò)展jar和插件放這里docs/官方文檔extras/一些輔助工具比如ant任務(wù)bin/jmeter.properties全局配置文件后面調(diào)優(yōu)會改它同樣建議配置環(huán)境變量JMETER_HOME指向安裝目錄然后把%JMETER_HOME%\bin加到Path里。這樣在任何目錄下敲jmeter就能啟動省得每次進(jìn)到bin目錄。2.4 Linux上的安裝差異要注意什么在Linux服務(wù)器上裝JMeter步驟大同小異但有幾個點(diǎn)要留意。第一用tar -zxvf解壓不是unzip。第二啟動腳本是jmeter.sh需要給它可執(zhí)行權(quán)限chmod x jmeter.sh。第三服務(wù)器上通常不裝圖形界面所以Linux下我們主要跑的是非GUI模式這恰恰是壓測最推薦的方式。# 解壓 tar -zxvf apache-jmeter-5.6.3.tgz -C /opt/ # 賦權(quán) chmod x /opt/apache-jmeter-5.6.3/bin/jmeter.sh # 啟動GUI有桌面的情況 /opt/apache-jmeter-5.6.3/bin/jmeter.sh我在生產(chǎn)壓測機(jī)上部署的時候通常會單獨(dú)建一個jmeter用戶因為壓測產(chǎn)生的臨時文件和日志量不小用root跑容易把文件權(quán)限搞亂。3. 中文界面、內(nèi)存與代理配置的實戰(zhàn)調(diào)整3.1 把界面改成中文的正確姿勢JMeter默認(rèn)是英文界面。改成中文有兩條路我推薦第二種。第一條路是臨時改啟動后點(diǎn)Options-Choose Language-Chinese (Simplified)。但這種方式下次啟動又變回英文了。第二條路是永久改打開bin/jmeter.properties找到language這一行默認(rèn)是注釋掉的改成languagezh_CN保存之后重啟JMeter界面就是中文的了。這里順便說一嘴雖然界面能改成中文但我建議關(guān)鍵術(shù)語還是記英文因為很多教程、報錯信息、插件文檔都是英文的你搜問題的時候搜中文術(shù)語搜不到東西。比如聚合報告其實是Aggregate Report線程組是Thread Group。3.2 內(nèi)存調(diào)優(yōu)別讓JMeter自己先崩了這是新手最容易忽略的一環(huán)。JMeter默認(rèn)的堆內(nèi)存比較小早期版本512MB壓測并發(fā)一上去JMeter自己就OOM了報錯往往是java.lang.OutOfMemoryError: Java heap space。調(diào)整方式有兩種。一種是改bin/jmeter.batWindows或jmeter.shLinux里的JVM參數(shù)找到HEAP相關(guān)的那行# Windows 的 jmeter.bat set HEAP-Xms2g -Xmx2g -XX:MaxMetaspaceSize512m # Linux 的 jmeter.sh HEAP-Xms2g -Xmx2g -XX:MaxMetaspaceSize512m-Xms是初始堆大小-Xmx是最大堆大小。我一般把這兩個設(shè)成一樣的值避免運(yùn)行中頻繁擴(kuò)容影響性能。設(shè)多大合適看壓測機(jī)配置和并發(fā)量。我的一般經(jīng)驗壓測機(jī)內(nèi)存建議堆大小可承載的大致并發(fā)4G-Xmx2g500以內(nèi)8G-Xmx4g1000左右16G-Xmx8g2000以上注意JMeter的并發(fā)能力還和腳本復(fù)雜度、監(jiān)聽器數(shù)量強(qiáng)相關(guān)。腳本里掛了一堆監(jiān)聽器內(nèi)存翻倍都不夠用。所以調(diào)內(nèi)存的同時也要精簡監(jiān)聽器。另一種方式是直接編輯bin/jmeter.properties不過新版JMeter更推薦改啟動腳本里的HEAP參數(shù)因為properties里改堆大小的方式在某些版本上不生效容易踩坑。3.3 代理配置與HTTPS錄制證書很多朋友問怎么用JMeter錄制HTTPS腳本。核心原理是JMeter作為一個代理服務(wù)器瀏覽器把請求發(fā)到JMeterJMeter轉(zhuǎn)發(fā)出去。但HTTPS有證書校驗所以要裝JMeter的根證書。操作步驟在測試計劃里添加HTTP(S) Test Script RecorderHTTP(S)測試腳本錄制器。設(shè)置監(jiān)聽端口默認(rèn)8080。點(diǎn)擊StartJMeter會在bin目錄下生成一個ApacheJMeterTemporaryRootCA.crt證書。把這個證書導(dǎo)入操作系統(tǒng)或瀏覽器的受信任根證書。瀏覽器設(shè)置代理指向localhost:8080然后正常操作JMeter就錄下來了。這塊新手最容易卡在證書導(dǎo)入上導(dǎo)入的時候一定要選擇受信任的根證書頒發(fā)機(jī)構(gòu)導(dǎo)入到個人那一欄是不生效的。另外錄完之后記得把瀏覽器代理關(guān)掉不然上不了網(wǎng)。3.4 插件管理與MQTT等擴(kuò)展安裝JMeter本身不含插件管理器需要單獨(dú)下載jmeter-plugins-manager的jar包放到lib/ext目錄下重啟JMeter后在Options菜單里就能看到Plugins Manager。裝插件我強(qiáng)烈推薦走插件管理器別手動往lib/ext里丟jar版本沖突很難查。比如你要做物聯(lián)網(wǎng)接口的MQTT壓測就在插件管理器里搜MQTT裝上就行。想擴(kuò)展圖表報告就裝jpgc系列插件。我的原則是能用插件管理器解決的就別手動拷貝jar。4. 從零搭建第一個HTTP壓測腳本4.1 測試計劃的整體結(jié)構(gòu)邏輯打開JMeter左邊默認(rèn)就有一個測試計劃Test Plan。理解它的層級結(jié)構(gòu)特別重要我用一個生活類比測試計劃就像一本書線程組是章節(jié)取樣器是段落里的句子監(jiān)聽器是給這些句子做的批注。層級關(guān)系是測試計劃Test Plan線程組Thread Group定義多少個用戶、怎么并發(fā)配置元件Config Element參數(shù)化、默認(rèn)值等取樣器Sampler真正的請求斷言Assertion判斷響應(yīng)是否符合預(yù)期前置/后置處理器Pre/Post Processor請求前后做處理監(jiān)聽器Listener收集結(jié)果理解了這個層級寫腳本就不會亂。我見過有同事把所有元件都堆在線程組下面平鋪結(jié)果作用域搞不清參數(shù)化經(jīng)常不生效就是因為沒理解層級。4.2 線程組參數(shù)怎么設(shè)才合理右鍵測試計劃 - 添加 - 線程用戶- 線程組。里面有幾個關(guān)鍵參數(shù)線程數(shù)Number of Threads就是并發(fā)用戶數(shù)模擬多少個虛擬用戶。Ramp-Up時間秒多少秒內(nèi)把這些線程全部啟動完。循環(huán)次數(shù)Loop Count每個線程跑多少次。這里有個關(guān)鍵的理解Ramp-Up不是隨便填的。假設(shè)線程數(shù)100Ramp-Up設(shè)10意思是10秒內(nèi)均勻啟動100個線程也就是每秒啟動10個。如果你把Ramp-Up設(shè)成1那就是1秒內(nèi)100個線程全部啟動瞬間沖擊容易把服務(wù)打掛也是不真實的用戶行為。我的經(jīng)驗是Ramp-Up時間設(shè)為線程數(shù)的1~2倍比較自然比如100并發(fā)Ramp-Up設(shè)100到200秒。除非你要測的是秒殺瞬間洪峰這種極端場景才刻意把Ramp-Up壓小。另外調(diào)度器勾上之后可以設(shè)定持續(xù)時長比如持續(xù)壓測300秒就比用循環(huán)次數(shù)來控制更直觀。4.3 HTTP請求取樣器的填寫要點(diǎn)右鍵線程組 - 添加 - 取樣器 - HTTP請求。核心字段字段填寫說明協(xié)議http 或 https服務(wù)器名稱或IP接口域名比如 api.example.com端口號默認(rèn)80https一般443不填也行方法GET / POST / PUT / DELETE等路徑接口路徑比如 /api/v1/order/query參數(shù)/消息體數(shù)據(jù)GET用參數(shù)表POST JSON用消息體數(shù)據(jù)POST提交JSON的時候一定要在HTTP信息頭管理器里加Content-Type: application/json否則后端解析不到會返回400。這個細(xì)節(jié)坑過很多人。{ userId: 10001, orderNo: SO202401150001 }加信息頭的方式右鍵HTTP請求 - 添加 - 配置元件 - HTTP信息頭管理器然后添加一行名稱填Content-Type值填application/json。4.4 第一次運(yùn)行和結(jié)果查看配置好之后先加一個監(jiān)聽器看結(jié)果。右鍵線程組 - 添加 - 監(jiān)聽器 - 查看結(jié)果樹。然后點(diǎn)綠色的啟動按鈕跑起來。第一次跑我建議線程數(shù)設(shè)1循環(huán)1次先確認(rèn)請求通了、返回正常。確認(rèn)沒問題之后再加大并發(fā)。查看結(jié)果樹里能看到請求的請求頭、響應(yīng)數(shù)據(jù)、狀態(tài)碼紅色表示失敗綠色表示成功。新手常見的情況是跑了之后全紅。這時候先看響應(yīng)數(shù)據(jù)里的報錯信息多半是地址填錯、參數(shù)缺了、或者需要登錄token。定位問題就是看請求標(biāo)簽里實際發(fā)出去的是什么和你在Postman里調(diào)通的請求對比一下差異就是問題所在。5. 參數(shù)化、斷言與關(guān)聯(lián)讓腳本接近真實業(yè)務(wù)5.1 CSV參數(shù)化讓每個用戶用不同數(shù)據(jù)如果所有線程都用同一個用戶ID去請求那壓測結(jié)果是不真實的緩存一命中數(shù)據(jù)全是假的。參數(shù)化就是讓不同線程用不同數(shù)據(jù)。最常用的是CSV Data Set Config。準(zhǔn)備一個csv文件userId,token 10001,token_aaa 10002,token_bbb 10003,token_ccc然后右鍵線程組 - 添加 - 配置元件 - CSV Data Set Config配置文件名csv的絕對路徑文件編碼UTF-8變量名稱userId,token分隔符逗號遇到文件結(jié)束符再次循環(huán)True遇到文件結(jié)束符停止線程False然后在HTTP請求里用${userId}、${token}引用。這里有個細(xì)節(jié)變量名要和csv表頭順序一致不是按名字匹配是按順序匹配的。所以變量名稱填的順序必須和csv列的順序?qū)ι稀L崾綾sv文件建議用UTF-8無BOM編碼用Excel另存為csv的時候容易帶上BOM導(dǎo)致第一列變量名帶個隱藏字符解析出問題。5.2 用戶定義變量與跨請求關(guān)聯(lián)除了csv還有兩種參數(shù)化方式。一種是用戶定義的變量適合放全局常量比如域名、公共token。它的作用域是整個測試計劃配一次處處可用。另一種是關(guān)聯(lián)也就是從上一個請求的響應(yīng)里提取值傳給下一個請求。這是接口測試?yán)镒畛R姷男枨蟊热缦鹊卿浤玫絫oken再帶著token去查詢。提取方式有幾種正則表達(dá)式提取器適合響應(yīng)是文本的場景。JSON提取器響應(yīng)是JSON時用它比正則直觀得多。舉個JSON提取器的例子。登錄接口返回{ code: 0, data: { token: eyJhbGciOiJI... } }在登錄請求下加JSON提取器配置變量名loginTokenJSON Path表達(dá)式$.data.token默認(rèn)值NotFound然后在后續(xù)請求里用${loginToken}引用。JSON Path的語法和大多數(shù)JSON解析庫一致$是根.data.token是路徑數(shù)組用[0]這種下標(biāo)。5.3 斷言判斷請求到底是成功還是失敗默認(rèn)情況下JMeter只看HTTP狀態(tài)碼200就算成功。但業(yè)務(wù)上200不代表業(yè)務(wù)成功可能返回了{(lán)code: 500, msg: 系統(tǒng)異常}。所以必須加斷言。最常用的是響應(yīng)斷言。右鍵請求 - 添加 - 斷言 - 響應(yīng)斷言測試字段響應(yīng)文本匹配規(guī)則包含 / 相等 / 匹配正則等測試模式填你期望出現(xiàn)的字符串比如code:0如果想判斷得更靈活可以用JSON斷言直接斷言某個JSON Path的值。也可以用BeanShell斷言或JSR223斷言寫腳本判斷。BeanShell斷言適合復(fù)雜邏輯比如需要判斷多個字段、做計算的情況import org.json.JSONObject; String response prev.getResponseDataAsString(); JSONObject json new JSONObject(response); int code json.getInt(code); if (code ! 0) { Failure true; FailureMessage 業(yè)務(wù)返回碼異常: code; }這里prev是JMeter內(nèi)置對象代表上一個取樣器的結(jié)果Failure和FailureMessage是BeanShell斷言的固定變量設(shè)置它們就能標(biāo)記斷言失敗。注意BeanShell性能較差高并發(fā)下會拖慢壓測。新版本更推薦用JSR223斷言 GroovyGroovy性能比BeanShell好很多。如果你的斷言邏輯簡單還是優(yōu)先用響應(yīng)斷言這種內(nèi)置的。5.4 文件上傳場景的腳本寫法有些接口需要上傳文件。JMeter在HTTP請求里勾選對POST使用multipart/form-data然后在文件上傳標(biāo)簽頁里填寫參數(shù)名說明文件名稱上傳文件的絕對路徑參數(shù)名稱后端接收文件的字段名比如 fileMIME類型比如 image/png、application/octet-stream我上傳測試時習(xí)慣準(zhǔn)備一個小文件比如幾KB的圖片別用幾十MB的大文件壓測否則瓶頸會在網(wǎng)絡(luò)傳輸上測不準(zhǔn)服務(wù)端。想測大文件場景另說。6. 非GUI壓測與結(jié)果報告解讀6.1 為什么正式壓測一定用命令行前面反復(fù)提過GUI模式只適合調(diào)試腳本正式壓測必須用命令行非GUI模式。原因很直接——GUI本身要渲染圖表、維護(hù)界面狀態(tài)非常消耗資源。同一臺機(jī)器GUI模式可能壓到300并發(fā)就卡了命令行模式能輕松上1000。命令行模式的基本命令jmeter -n -t test_plan.jmx -l result.jtl -e -o ./report參數(shù)說明參數(shù)含義-n非GUI模式運(yùn)行-t指定腳本文件.jmx-l指定結(jié)果文件.jtl會覆蓋同名文件-e壓測結(jié)束后生成HTML報告-o指定HTML報告輸出目錄目錄必須為空或不存在的-J設(shè)置JMeter屬性比如 -Jthreads100這里有幾個坑要提醒。第一-l指定的jtl文件如果已存在會直接覆蓋所以每次壓測換個文件名或者先刪舊的。第二-e -o一起用時報告目錄必須不存在或為空否則會報錯退出。第三如果腳本里配置了結(jié)果輸出路徑命令行參數(shù)會覆蓋它。6.2 HTML報告的打開與關(guān)鍵指標(biāo)壓測跑完后report目錄下會生成index.html雙擊用瀏覽器打開報告相當(dāng)完整。重點(diǎn)看幾個指標(biāo)響應(yīng)時間Response Times關(guān)注平均、90%、95%、99%分位。平均值會被極端值拉偏看95%和99%分位更有意義。吞吐量Throughput單位是每秒完成的請求數(shù)近似我們的QPS。錯誤率Error %超過1%就得警惕了。活躍線程數(shù)曲線能看到壓力加載的過程。我判斷一個接口能不能扛住的標(biāo)準(zhǔn)一般是99%分位響應(yīng)時間在可接受范圍內(nèi)比如500ms以內(nèi)錯誤率低于0.1%吞吐量達(dá)到目標(biāo)QPS。三個指標(biāo)是聯(lián)動的不能只看一個。6.3 結(jié)果文件的后續(xù)加工jtl結(jié)果文件本質(zhì)是個csv或者xml可以用Excel打開也可以用腳本分析。我經(jīng)常做的是把jtl導(dǎo)入到數(shù)據(jù)庫用SQL做更細(xì)的漏斗分析比如按時間段看響應(yīng)時間變化找出性能抖動的時刻。如果要精簡jtl大小可以在jmeter.properties里配置只記錄需要的字段jmeter.save.saveservice.output_formatcsv jmeter.save.saveservice.response_datafalse jmeter.save.saveservice.samplerDatafalse把響應(yīng)數(shù)據(jù)關(guān)掉能大幅減小文件壓測時性能也更好。需要排查具體請求的時候再臨時打開。6.4 分布式壓測的初步思路單臺壓測機(jī)的能力是有天花板的想壓幾千上萬并發(fā)就要用分布式。JMeter支持一臺master控制多臺slave。思路是slave機(jī)上啟動jmeter-servermaster機(jī)在jmeter.properties里配置remote_hosts列出所有slave的IP然后命令行用-R指定slave運(yùn)行。腳本和數(shù)據(jù)文件要在所有slave上保持一致。jmeter -n -t test_plan.jmx -R 192.168.1.101,192.168.1.102 -l result.jtl分布式也有坑slave的時間要同步、網(wǎng)絡(luò)要互通、腳本里的文件路徑要一致。我一般先用1個slave跑通再加更多。7. 那些年踩過的坑常見報錯與排查思路7.1 java.io.IOException: error writing to server這個報錯在熱搜詞里也出現(xiàn)了非常典型。意思是在往服務(wù)端寫數(shù)據(jù)的時候出錯了。常見原因有這么幾個連接被服務(wù)端提前關(guān)閉可能是服務(wù)端處理超時、連接池耗盡主動斷開了連接。上傳的數(shù)據(jù)太大發(fā)送大文件或者超長請求體時超過服務(wù)端允許的限制。網(wǎng)絡(luò)不穩(wěn)定壓測機(jī)到目標(biāo)服務(wù)之間網(wǎng)絡(luò)抖動。JMeter自身配置問題比如httpclient4.retrycount設(shè)置不合理。排查思路先看服務(wù)端日志確認(rèn)服務(wù)端有沒有報錯再看是不是壓測的并發(fā)太高超過了服務(wù)端承受能力然后檢查請求體大小是否合理最后可以適當(dāng)調(diào)整JMeter的HTTP客戶端參數(shù)。這個錯誤本質(zhì)上更多是服務(wù)端或網(wǎng)絡(luò)的問題而不是JMeter本身的bug。7.2 內(nèi)存溢出與堆棧調(diào)整報OutOfMemoryError的時候先別慌。按這個順序處理確認(rèn)是不是GUI模式下壓測的是的話換成命令行。檢查監(jiān)聽器是不是掛太多尤其是查看結(jié)果樹這種全量記錄的壓測時務(wù)必關(guān)掉。加大堆內(nèi)存改HEAP參數(shù)。減少不必要的斷言和腳本校驗。我遇到過一次腳本里每個請求都掛了BeanShell斷言壓到200并發(fā)直接OOM改成JSR223 Groovy之后內(nèi)存曲線就平穩(wěn)了。所以腳本本身的效率很關(guān)鍵。7.3 響應(yīng)亂碼怎么處理響應(yīng)中文亂碼是最常見的看著像bug其實不是bug的問題。JMeter默認(rèn)的編碼有時候不對。解決方式在jmeter.properties里設(shè)置sampleresult.default.encodingUTF-8?;蛘哂煤笾锰幚砥鰾eanShell PostProcessor設(shè)置編碼prev.setDataEncoding(UTF-8)?;蛘叽_認(rèn)HTTP請求里的內(nèi)容編碼填了UTF-8。改完properties記得重啟JMeter生效。7.4 參數(shù)化數(shù)據(jù)不生效的排查鏈路參數(shù)化不生效我總結(jié)的排查順序是變量引用寫對沒是不是${var}格式花括號別忘了。CSV Data Set Config的作用域?qū)Σ粚κ遣皇欠旁诹苏埱蟮母腹?jié)點(diǎn)上。csv路徑對不對路徑里的反斜杠在Windows下有時要轉(zhuǎn)義。csv編碼有沒有BOM。變量名順序和csv列順序?qū)Σ粚Φ蒙?。如果引用的變量在日志里顯示${var}原樣說明變量根本沒被替換那一定是配置沒生效。排查的時候打開日志bin/jmeter.log里面有詳細(xì)的變量解析記錄比瞎猜快多了。7.5 我的幾條壓測紀(jì)律最后分享幾條我個人定下的壓測紀(jì)律供參考壓測前先和運(yùn)維、開發(fā)打招呼別突然給生產(chǎn)環(huán)境來一波容易出事。壓測環(huán)境盡量和生產(chǎn)配置一致否則數(shù)據(jù)沒法參考。先小并發(fā)驗證腳本正確性再逐步加壓別一上來就拉滿。每次壓測只變一個變量否則出了問題不知道是哪個因素導(dǎo)致的。保留每次壓測的腳本和報告做趨勢對比時非常有用。這套流程我從零起步搭起來中間踩過的坑基本都寫在上面了。JMeter這東西看著界面復(fù)雜實際上把線程組-取樣器-斷言-監(jiān)聽器這條主線理清楚剩下的就是不斷練手。建議你現(xiàn)在就去找個測試接口按第四節(jié)的步驟跑一個最簡單的GET請求跑通之后再一步步加參數(shù)化、斷言、關(guān)聯(lián)。真正上手跑一遍比看十篇教程都管用。