jMeter解決failed?

jMeter測試單個介面測試都沒有問題,多個介面依次測試,就會有部分The target server failed to respond,有的會返回Connection reset。我們一步步來看看怎麼解決

找到造成failed to respond的原因

先看一下服務端的相關配置:

預設的tcp_keepalive_time是7200;

tomcat的server.xml的配置 connectionTimeout是20s

jMeter解決failed to respond Connection reset

jMeter解決failed to respond Connection reset

從抓包檢視瀏覽器中一個正常訪問的開始

----

客戶端ip:192.168.1.101,服務端ip: 192.168.1.50

訪問 /api/vi/home

----

從下圖wireshark的抓包資料,可以看到22行,客戶端回了一個ACK,這次請求的資料已經傳出完畢了,服務端連線的狀態是 ESTABLISHED。

----

20s後,服務端發了一個FIN+ACK,主動關閉這個連線(因為tomcat中設定了20s超時),四次揮手這個連線就關閉了。

jMeter解決failed to respond Connection reset

如果 /api/vi/home 這個訪問響應完後的20s內,有新的請求產生,就會複用這個tcp連線,就不用在3次握手了。

----

從下圖可以看到

第一次請求/api/vi/home 經過了三次握手

緊接著請求/api/v1/home/seckill?sec=2 就直接傳資料了

這是複用了tcp連線。

jMeter解決failed to respond Connection reset

如果超過了20s,連線被服務端主動關閉了,瀏覽器中再次請求的時候,就會建立一條新的連線。

----

這也就是HttpClient的連線池機制,可以複用tcp連線,這樣能有效減少服務端開銷和縮短響應時間。

----

在瀏覽器中訪問,服務端主動去關閉的時候,客戶端也就跟著關閉了,四次揮手!

jMeter解決failed to respond Connection reset

但在jMeter中,如果20s超時,服務端發來FIN+ACK,客戶端回一個ACK,但客戶端並不會再回一個FIN+ACK,也就是說不理會服務端的主動關閉

----

這時服務端的tcp連線的狀態是FIN_WAIT2, 客戶端的tcp連線的狀態是CLOSE_WAIT。

這也就是為什麼服務端有很多FIN_WAIT2的原因!

jMeter解決failed to respond Connection reset

到下一個介面測試的時候,複用了這個連線,服務端tcp就會返回RST,而http就是空應答,HttpClient在解析HTTP頭時,發現沒有資料,因為沒有返回HTTP資料包,而是返回了TCP資料包。

----

就會在jMeter中看到如下錯誤:

Response code: Non HTTP response code: org.apache.http.NoHttpResponseException

Response message: Non HTTP response message: The target server failed to respond

jMeter解決failed to respond Connection reset

復現空閒超時被服務端主動關閉的情況

這是jMeter中ideltimeout的配置:

----

bin/jmeter.properties 這個檔案中,有關於ideltimeout的配置,目前是註釋的。

jMeter解決failed to respond Connection reset

我們測試執行緒數是2,兩個介面(seckill介面,home介面),迴圈次數1

jMeter解決failed to respond Connection reset

seckill介面的地址:

/api/v1/home/seckill?sec=${sec}

----

home介面的地址:

/api/v1/home

----

在seckill介面中

/api/v1/home/seckill?sec=1的時候 sleep了30s

/api/v1/home/seckill?sec=2的時候,正常處理

這樣就能保證,/api/v1/home/seckill?sec=2的這條連線等到測試home介面的時候,已經超過了20s,被服務端主動關閉了

----

看抓包結果:

(ideltimeout註釋了下的情況)

jMeter解決failed to respond Connection reset

可以看到: 埠57513(/api/v1/home/seckill?sec=2),在空閒20後(51行)的時候,被服務端主動關閉,等到下一個介面/api/v1/home要用的時候,服務端返回RST(63行)

----

這是jMeter中返回的結果:

jMeter解決failed to respond Connection reset

我們開啟ideltimeout,看看這個timeout好不好使

ideltimeout == 10s時:

----

可以看到20s後(53行)被服務端主動關閉,/api/v1/home/seckill這個介面併發完成後(69行是都完成了),才在(70行)主動去關閉埠為57590的這個超時連線。

這都超了33秒了,早就超過ideltimeout==10s的設定了

----

但這個設定還是還是管用的,不然也不會有(70行)的主動關閉連線。

jMeter解決failed to respond Connection reset

我們再看看ideltimeout == 20s的時候:

----

可以看到無論是20s 還是10s,連線都不是實時釋放的,都是等這個介面測試完,才去釋放的,也就是說,這個ideltimeout 是等一個介面測試完,然後再去檢視每個連線的空閒時間,如果有的超過了ideltimeout,就主動關閉它。

jMeter解決failed to respond Connection reset

那麼我們就知道:

jMeter有兩種主動關閉連線的方式

----

1:一個介面併發完,空閒時間超過 ideltimeout 的執行緒,幹掉

2:全部測試完成,主動關閉所有連線。

介面測試總結

通過以上可總結三種情況錯誤的情況如下:

(以2000併發為例)

----

1:ideltimeout不設定,只設置connectionTimeout==20s

----

一批介面中

第一個介面肯定不會出現,因為他都是新建的tcp連線。

----

第二個介面容易出現RST,因為第一個介面新建連線比較耗時,容易造成測到第二個介面的時候,一些連線已經超過了20s,被服務端主動關閉了。

----

耗時的介面上,容易出現RST

比如介面4,複用介面3的2000連線(我們以1~2000標記),說是併發執行,其實在服務端也是個佇列,假設到複用1900以後的了連線了,1900以前已經耗時了20s, 這1900以後的連線其實已經被服務端主動關閉了。(有些連線在介面3中已經空閒了一段時間,到介面4都不用20s就被關閉了 )

----

耗時的介面的下一個介面,容易出現RST,原因耗時介面到下一個介面的時候,有些空閒的時間比較長

----

所以如果不設定ideltimeout,很容易造成累計效應,越到最後,可能出錯的機率越高

2:ideltimeout < connectionTimeout的情況

----

設定 ideltimeout == 10s,設定connectionTimeout==20s

----

第一個介面肯定不會出現,同上

----

第二個接口出錯的機率比第一種情況就小很多,因為到第二個介面的時候沒有連線 的空閒時間是超過了10s的,只有連線複用的時候如果空閒超過了20s,被服務端主動關閉的連線才會出錯。

----

耗時的介面上,容易出現RST,但比第一種情況機率小一些。

----

耗時的介面的下一個介面,比第一種情況機率也小一些。

3:當Ideltimeout > connectionTimeout時:

----

設定 ideltimeout == 60s,設定connectionTimeout==20s

----

他比第一種情況好,比第二種情況差。

所以出錯的機率大概是這樣的:(由大到小)

1:ideltimeout不設定,只設置connectionTimeout

2:Ideltimeout > connectionTimeout

3:ideltimeout <= connectionTimeout

解決辦法

正常的客戶端訪問,不會出現這樣的情況,因為正常通訊的情況下,服務端主動關閉,客戶端連線也會釋放掉。

----

但是jMeter中,服務端主動關閉,他根本就不理會。那麼有沒有jMeter中實時主動關閉的辦法那?

----

去掉勾選Use KeepAlive

連線就不會複用,這樣也就不存在空閒超時,被服務端幹掉的情況了。

但帶來的是效能的開銷,因為tcp每次都要關閉然後重建。

jMeter解決failed to respond Connection reset

可是,正常瀏覽器訪問請求頭中也是帶Connection:keep-alive的,所以去掉的話,測試出的吞吐量就不太合理。

jMeter解決failed to respond Connection reset

那這個問題就落在服務端的主動關閉上了,不讓服務端主動關閉就行了。

----

把 connectionTimeout 儘可能的調大,

建議 connectionTimeout = 最耗時介面的一次併發的總時間 * 介面個數

Ideltimeout <= 最耗時介面的一次併發的總時間

----

測試完,把connectionTimeout這個值在改回原值即可。

問題, 介面, 服務端,
相關問題答案