Jmeter的客戶端實現與Keep-Alive


Jmeter的客戶端實現與Keep-Alive

沒有時間的朋友直接讀結論即可。

0. 結論

  1. 當客戶端實現為Java,使用Keep-alive時

    1. Vuser越大,保持的時間越短,且tcp連接會斷不完全,造成雙倍甚至3倍Vuser連接的情況。

    2. Vuser越小,保持的時間越長,但過幾分鍾甚至10幾分鍾后,tcp連接還是會變。

      這個現象的原因不詳。

  2. 當客戶端實現為HC4,使用Keep-alive時

    1. 修改jmeter.propertieshttpclient4.time_to_live的數值即可保持連接時間。單位為ms
    2. httpclient4.time_to_live的值為0時,為永久保持
    3. Jmetr 5.3以下的版本,默認保持間為2s,5.3以上版本更改為60s。

以上的結論都基於服務端快速響應,不涉及超時時間等問題。

1.緣起

1.1 起因

起因是我需要使用Jmeter發送HTTP請求,並且保持長連接。

再細化下需求,保持多久的長連接?

  1. 固定時長,到時間自動釋放
  2. 永久時長,只要不空閑超時

1.2 初步嘗試

既然要做Jmeter的HTTP長連接,肯定就是要勾選keep-alive

接着就去進行測試壓測了,結果發現壓測的端口在不斷的變化,並沒有實現一個長連接的效果。

查看Jmeter壓力機 查看具體端口

  • windows的話使用 netstat -ano | find "ip端口" | find "ESTABLISHED" | find "IP地址"

  • linux的話使用 ss -ant | grep "ip端口" | grep "ES" | grep"IP地址"

只看端口變化還是有一定的問題,遂抓取壓測時候的包查看。

抓包命令:

  • windows 使用wireshark抓包
  • linux 使用 tcpdump tcpdump -i 網卡名 -w 保存的報文名字.pcap 之后使用wireshark解析

一看果然,只有在一個時間段進行了保持連接,之后客戶端就主動釋放了

看下圖,我只有3個Vuser,如果一直保持了連接,是不可能建立出7個連接的。

觀察了下時間,正好2秒釋放掉的。

如法炮制,我觀察了好幾個tcp連接,都是2秒鍾就主動釋放了。

所以有理由推測,這個保持時間是個可配置項。

1.3 Jmeter客戶端實現

想到時間可以配置,我來到了HTTP的高級頁面,在這里,發現了HTTP的客戶端實現方式。

  • HttpClient4 簡稱HC4
  • Java

為什么會有3個客戶端實現方式呢?我查詢了官方文檔,貼在下面。

Jmeter客戶端3種實現方式官方文檔

簡單的來說就是:

  • HC4 實現 -----多數情況都在使用的,功能豐富且細化。
  • Java實現 -----在實現HTTP時候會有限制
  • 空 ---- 讀取配置文件來決定使用什么,默認是HC4

1.4 Java+keep-alive?

之前使用的是HC4+keep-alive 無法一直保持,那么Java + keep-alive呢?抱着這個想法,我測試了下。

Vuser 我依然給了3個,下面是線程組配置

結果非常驚喜,抓包查看可以一直保持!

此處其實是有問題的,先埋個坑。

2. 壓力測試

2.1 測試

基於前面的測試報文,很開心,於是直接將這種方式進行了壓力測試。

設置Vuser為200,詭異的事情發生了,壓力機報了好多異常錯誤信息,查看jmeter.log也沒有報錯信息。一時間不知所措。

日志就不截圖了,和上圖一樣。

於是,我開始抓包,抓包看。

結果發現長連接沒有保持住,能過濾出tcp的連接好幾百,正常應該就是200個連接一直在保持。

但是報文還是看出幾個點:

  • tcp保持時間:有的保持了2s,有的10s,有的15s,沒有規律,
  • tcp釋放:每次都是由Jmeter主動釋放(主動發送Fin)。

查看壓力機的端口使用情況:

明顯是TIME_WAIT過多,為了更進一步的確定,我產生了jtl 和 debug級的log。

2.1 產生jtl和debug級日志

修改日志等級

修改bin/log4j2.xml 將info 修改為debug

產生jtl和log

linux 執行命令 jmeter -n -t ./xxxxx.jmx -l test.jtl -j debug.log

使用GUI的Jmeter查看jtl

在測試計划里添加 查看結果樹,導入產生的 jtl

確實是產生了好多失敗的請求,查看某一個請求,發現HTTP的Message為 無法分配請求地址。

這也側面證明了確實是端口不夠用,導致無法請求了。

2.3 迷惑點

到目前為止,我們需要解決的問題

  1. HC4 的長連接時間 怎么設置?
  2. 永久連接(使用Java實現)為什么會主動釋放tcp?

3. stack overflow&看源碼

查看Jmeter的源碼源碼和版本下載地址

3.1 HTTPJava

首先我去看了使用Java實現HTTP? 直接看HTTPJavaImpl.java即可

在論壇看到這么個帖子

我的web后台是沒有設置60s超時時間的,查看http的報文也沒有max的參數。-----至此,問題無法解決

配置參數

通過HTTPJavaImpl.java可以看出,只有httpsampler.obey_contentlengthhttp.java.sampler.retries參數是影響JavaHttp的實現的。

通過字面和Jmeter手冊

  • httpsampler.obey_contentlength : 服從內容長度
  • http.java.sampler.retries :重試次數,默認為0,不進行重試

無關緊要,往下走。

sample函數

sample為核心函數,負責創建連接,接收信息的

結合debug的日志,我們幾乎可以斷定就是在塊發生了IO異常

誰拋出的異常呢?應該是setupConnection函數

setupConnection函數

猜測是這里出了問題。

看源碼也是沒能找到為什么java的會主動釋放tcp。影響java的http實現就是2個參數,之后又看到了一個bugbug55023,說的是一個其他參數影響了Java實現的HTTP的吞吐值,這里懷疑也可能是某個未知bug。並且論壇在討論相關實現的時候都在推薦HC4,不推薦JAVA(實現的功能少)。

至此,我仍然沒有找到為什么在使用JAVA實現 + keep-alive時候,會不斷的釋放+新建TCP連接,如果有大佬清楚,麻煩留個言,討論下

3.2 HTTP HC4

既然JAVA的路走不通了,轉回頭研究下HC4的實現

查看Jmeter的配置文件jmeter.properties發現幾個參數很是可疑。

378 httpclient.timeout  
437 httpclient4.idletimeout
445 httpclient4.time_to_live

手冊查看得知

也即是

  • httpclient.timeout : 這個是socket的連接超時 時間,默認0是不超時的
  • httpclient4.idletimeout:在服務器沒有發keep-alive的情況下,http的連接超時時間,也就是在服務器沒有發keep-alive的情況下,還能保持多少秒。默認是不保持。
  • httpclient4.time_to_live: http的生存時間,默認時間60s。

這個httpclient4.time_to_live好像是決定的參數,看了Jmeter的配置,怎么是2000,不是6000呢?

2000? 想起了第一次抓包的tcp時間就是2s。看來就是這個參數了。那怎么是2000,不是6000呢?

我查看了Jmeter版本,原來本地用的是5.2.1版本,而5.3.1時候Jmeter將這個視作bug進行更改了。

bug64289變更記錄

接下來就是實驗,改httpclient4.time_to_live之后確實可以固定長度的連接時長,但是如何大的時長和永久呢?

TIME_TO_LIVE

看了下Jmeter源碼HTTPHC4Impl.java,發現了下面的語句。

這個語句很有意思,這定義了一個 **int **類型的 int類型的最大值是 2 的 31 次方 - 1 = 2147483648 - 1 = 2147483647 Integer.MIN_VALUE = -2147483648

2147483647/1000/3600/24 = 24.8 也就是說可以保持24.8天,已經滿足使用了。

但是我們仍往下查看,發現只是將TIME_TO_LIVE傳給了HttpClientBuilder

接下來去看下HttpClient的源碼 HttpClientBuilder類。

可以看到,HC4是以long進行接收的,但是Jmeter把范圍縮小了,變為了int。

但是還是沒解決永久的連接啊,於是突發奇想,試試值為0呢,沒想到竟然可以使用,

我測試了半天發現仍可以保持連接,其實感覺也就是不合法的值為MAX_VALUE了,這個屬於猜測,我沒有找到異常數值的相關的代碼。

小結

要保持長連接選擇 HC4 實現,不要選擇JAVA,連接時長設置httpclient4.time_to_live該參數。

在回過頭看看官方的解釋文檔,無法控制如何重新使用連接,這句話好像有所解釋,但是我理解的不深入。所以還是使用HC4吧,別用Java了

參考

文章1


免責聲明!

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



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