NoHttpResponseException問題分析解決記錄
新項(xiàng)目上線遇到NoHttpResponseException的問題
大概11000筆發(fā)到C系統(tǒng)的交易會出現(xiàn)15筆會因這種異常而導(dǎo)致失敗,對月交易量在近三億的系統(tǒng)來說,按照這樣的比例也會有4萬多筆的交易失敗,這種嚴(yán)重影響客戶體驗(yàn)的現(xiàn)象堅(jiān)決不能容忍。
按照套路網(wǎng)上搜了下這種出現(xiàn)這種異常的原因以及解決辦法,apache網(wǎng)站的解釋是:
In some circumstances,usually when under heavy load, the web server may be able to receive requests but unable toprocess them. A lack of sufficient resources like worker threads is a good example. This may cause the server to drop the connection tothe client without giving any response. HttpClient throws NoHttpResponseException when it encounters such a condition. In most cases it is safe to retry a method that failed with NoHttpResponseException.
意思就是當(dāng)服務(wù)器端由于負(fù)載過大等情況發(fā)生時(shí),可能會導(dǎo)致在收到請求后無法處理(比如沒有足夠的線程資源),會直接丟棄鏈接而不進(jìn)行處理。此時(shí)客戶端就回報(bào)錯(cuò):NoHttpResponseException。 建議出現(xiàn)這種情況時(shí),可以選擇重試。
聯(lián)系了W公司的同事,確認(rèn)他們的C系統(tǒng)的負(fù)載還遠(yuǎn)未達(dá)到過載的程度,而且我們發(fā)到他們B系統(tǒng)的交易從來沒有出現(xiàn)過這種異常,他們也無法解釋這種異常產(chǎn)生的原因。
抓包看下tcp連接交互的情況
兩筆異常交易的共同點(diǎn)就是(以圖二為例)C系統(tǒng)在2891個(gè)包發(fā)來了揮手,然后在2893個(gè)包RST了連接,導(dǎo)致我方系統(tǒng)第2888、2889發(fā)的請求沒有收到響應(yīng)就異常結(jié)束了。
2個(gè)問題(自問自推測)
1. C系統(tǒng)為什么會發(fā)送結(jié)束連接的FIN揮手包?
注意到圖二在第2882個(gè)包C系統(tǒng)返回前一個(gè)請求的響應(yīng)完成(10:16:25),到第2888個(gè)包(10:16:46)我方發(fā)送下一個(gè)請求,之間有個(gè)21s的空閑間隔,圖一中C系統(tǒng)在發(fā)出FIN揮手包之前也有一個(gè)20s的空閑間隔,會不會是C系統(tǒng)的服務(wù)器會在每個(gè)連接空閑20s后自動就會發(fā)起斷開連接呢?再看下圖三正常結(jié)束交易的tcp流,也是在收到客戶端的確認(rèn)包后有20s的空閑間隔。
基本上可以推斷出C系統(tǒng)的服務(wù)器會在連接空閑20s后自動發(fā)起斷開連接。
2. C系統(tǒng)為什么會直接發(fā)出第2893個(gè)RST包,而不是發(fā)出正常的Ack確認(rèn)包?
按照圖二的tcp流序列,客戶端發(fā)出的第2888個(gè)包在收到服務(wù)端發(fā)送的第2891個(gè)FIN包之前,只個(gè)是在客戶端抓的包,請求的網(wǎng)絡(luò)傳輸時(shí)間。C系統(tǒng)的服務(wù)端發(fā)出的FIN包時(shí)很可能還沒收到我方發(fā)送的第2888個(gè)請求。即服務(wù)端發(fā)送FIN包后,馬上就收到了第2888個(gè)請求包,以及第2892個(gè)[FIN、Ack]包,自身無法判斷是正常結(jié)束,所以就發(fā)出來RST包,關(guān)閉連接。
我方系統(tǒng)是用httpclient4.3的60s的長連接發(fā)送請求,使用的http1.1協(xié)議連接是默認(rèn)keepalive的,同一個(gè)線程的多個(gè)請求可以復(fù)用同一個(gè)長連接。正是由于c系統(tǒng)發(fā)出FIN包的時(shí)間,與我方在連接空閑了20s時(shí)仍使用這個(gè)連接發(fā)送數(shù)據(jù)時(shí)之間微妙的時(shí)間差,所以導(dǎo)致出異常的交易都滿足這樣一個(gè)現(xiàn)象:即請求發(fā)出去才幾十毫秒就收到了異常。
解決
基本上明確了異常的原因,那解決辦法是?
1. 協(xié)調(diào)W公司變更配置
前面已經(jīng)說了我方系統(tǒng)發(fā)送到W公司B系統(tǒng)的交易,沒有出現(xiàn)過這種異常,說明B系統(tǒng)的服務(wù)端在我方長連接存在的60s時(shí)間里沒有主動發(fā)起斷開此連接,推測B系統(tǒng)的連接最大空閑時(shí)間是大于60s。這個(gè)需要抓下與B系統(tǒng)的tcp包就可以分析出B系統(tǒng)有沒有主動斷開長連接,空閑多少秒斷開兩個(gè)信息。那可不可以協(xié)調(diào)W公司,請他們將兩個(gè)系統(tǒng)的連接保持最大空閑時(shí)間設(shè)置為一致呢?這個(gè)只能盡力。
2. 優(yōu)化我方系統(tǒng)
1)http請求使用重發(fā)機(jī)制,捕獲NohttpResponseException的異常,重新發(fā)送請求,重發(fā)3次后還是失敗才停止。由于不知道客戶端捕獲到NohttpResponseException這個(gè)異常后,客戶端是否自動關(guān)閉了這個(gè)連接,每次重發(fā)都需要新建連接發(fā)送。新建連接不存在太長的空閑時(shí)間問題,因此能夠通過重發(fā)解決交易失敗的問題。
2)我方系統(tǒng)主動檢查每個(gè)連接的空閑時(shí)間,允許設(shè)置連接的最大空閑時(shí)間M,即客戶端建立的連接空閑M秒后,自動發(fā)起斷開連接。只要這個(gè)M時(shí)間小于服務(wù)端的最大空閑時(shí)間,將完全避免服務(wù)端主動斷開連接導(dǎo)致的異常。
與同事交流,之前鄙司另一個(gè)系統(tǒng)到微信支付請求也遇到同樣的NohttpResponseException異常,tcp抓包信息如下圖:
第47970個(gè)包是服務(wù)端發(fā)來的FIN包,收到響應(yīng)的ack包立刻就想斷開連接(確認(rèn)是開啟keep-alive的,連接保持),而客戶端又發(fā)送了新的請求包過去,服務(wù)端就發(fā)送了三條RST包,斷開了連接。異常的原因推測是apache網(wǎng)站的解釋,對方負(fù)載過大主動斷開連接,也按照網(wǎng)站推薦的做法,捕獲異常重發(fā),后面就沒有再遇到因這種異常而引起交易失敗。
以上就是NoHttpResponseException問題分析解決記錄的詳細(xì)內(nèi)容,更多關(guān)于NoHttpResponseException問題解決的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java如何實(shí)現(xiàn)http接口參數(shù)和返回值加密
這篇文章主要介紹了Java如何實(shí)現(xiàn)http接口參數(shù)和返回值加密問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11Java+Appium實(shí)現(xiàn)屏幕錄制功能
這篇文章主要介紹了Java如何利用Appium實(shí)現(xiàn)屏幕錄制功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06SpringBoot中處理的轉(zhuǎn)發(fā)與重定向方式
這篇文章主要介紹了SpringBoot中處理的轉(zhuǎn)發(fā)與重定向方式,分別就轉(zhuǎn)發(fā)和重定向做了概念解說,結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-11-11詳解spring mvc 請求轉(zhuǎn)發(fā)和重定向
這篇文章主要介紹了詳解spring mvc 請求轉(zhuǎn)發(fā)和重定向,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-02-02idea使用pagehelper實(shí)現(xiàn)后端分頁功能的步驟詳解
這篇文章主要介紹了idea使用pagehelper實(shí)現(xiàn)后端分頁功能的步驟,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09