2019-06-21

http阻塞(http請求被掛起,長時間處于pending 狀態(tài))

不知道大家有沒有遇到這種情況,就是當你再進行開發(fā)的時候,有時候突然會出現(xiàn)http請求一直卡在pending這個狀態(tài),甚至有時候卡了一兩分鐘,然后這個接口竟然沒有報錯,請求的數(shù)據(jù)被成功的返回了。當時我遇到這種情況的時候感覺很神奇,一個接口竟然可以等幾分鐘還不報錯,但是這個東西因為是偶發(fā)的,所以后面也就沒有去深入研究,直到前幾天突然想到了這個問題,今天就想去深入了解一下。

分析

要想搞明白為什么會出現(xiàn)這種情況,你必須對http協(xié)議有所了解,其中http1.1是支持長連接的,什么是長連接,就是一個tcp連接可以處理多個http請求。但是有一個缺點就是,必須等上一個http請求返回結(jié)果之后才能繼續(xù)處理下一個請求,這有可能會造成時間上的浪費。而問題正是出現(xiàn)在長連接的請求上。因為我們發(fā)現(xiàn)出現(xiàn)問題的時候總是有多個http請求復用同一個tcp連接的情況出現(xiàn),因此可以斷定是長連接引起的問題。

猜想

根據(jù)上文分析,我這邊有兩個猜想:

1.由于http1.1的長連接的缺點,可能是因為等待上一個請求返回結(jié)果的時間過長,導致請求一直處于pending狀態(tài),但是經(jīng)過測試可以證明這個想法是錯誤的。因為我發(fā)現(xiàn)復用同一個tcp連接的http請求,當上一個請求已經(jīng)返回結(jié)果之后,下一個請求依然長時間處于pending狀態(tài),所以說這個猜想是不成立的。

2.既然不是因為等待時間的問題,我們就大膽的猜測這個長連接(TCP連接)因為某種原因異常的斷開了,所謂異常的斷開就是單方面的斷開,也就是服務器知道斷開了,瀏覽器卻不知道該連接已經(jīng)斷開了。因此,瀏覽器仍然會通過該tcp連接去發(fā)送請求,但是此時服務器已經(jīng)發(fā)現(xiàn)該連接斷開了,所以會拒絕該次請求,從而引起一系列的問題。但是它會引起什么問題呢,就是http請求會被長時間掛起,這有一篇博客在這方面寫的非常好,大家可以去看一下。關(guān)于請求被掛起頁面加載緩慢問題的追查_知識庫_博客園

解決辦法

1.調(diào)整系統(tǒng)內(nèi)核參數(shù)

? 我們已經(jīng)知道出現(xiàn)該問題是因為tcp連接是異常斷開的,只要解決連接異常斷開的問題就好了。當然這涉及到tcp的異常連接問題,通過查閱各種資料發(fā)現(xiàn),原因如下:服務器關(guān)閉連接的時候,調(diào)用的是Socket.close()方法,該方法會返回一個RST(RST=1:該字段為一表示當前 TCP 連接出現(xiàn)嚴重問題,可能需要重新建立 TCP 連接,也可以用于拒絕非法的報文段和拒絕連接請求。),然后服務器就單方面的斷開連接了,因為RST這個標志位瀏覽器不能識別,瀏覽器只能識別正常斷開連接的FIN標志位,只有返回這個標志位,瀏覽器才知道這個連接被斷開了(這個地方看不懂的大家可以去仔細的看一下TCP相關(guān)的知識)。所以說,解決這個問題辦法就是不讓它調(diào)用Socket.close方法,也就不會返回RST標志位,解決這個問題涉及到系統(tǒng)內(nèi)核的問題了,查閱相關(guān)資料,給出解決方案:

2.短連接

這是最簡單的解決辦法,因為這種情況只出現(xiàn)在長連接的情況下,所以我們采用最簡單最粗暴的方式來解決它,就是服務器和客戶端同時采用短連接,這樣就算再怎么異常斷開也沒有關(guān)系,因為我們采用的短連接根本不會出現(xiàn)復用tcp連接的情況,想想就很爽。但是呢,這種解決辦法也有缺點,每次請求都要通過三次握手建立tcp連接,就會浪費大量的三次握手的時間,這對于一般的應用來說,這點時間算不了什么。但是對于那些億級以上的應用,節(jié)省的時間是很可觀的。

至于要采用哪種方式去解決這個問題呢,就要根據(jù)具體情況來定了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容