一次http請求,誰會先斷開TCP串連?什麼情況下用戶端先斷,什麼情況下服務端先斷?

來源:互聯網
上載者:User

標籤:href   time_wait   先來   coding   結果   限制   多個   狀態   揮手   

我們有2台內部http服務(nginx):

201:這台伺服器部署的服務是account.api.91160.com,這個服務是供前端頁面調用;

202:這台伺服器部署的服務是hdbs.api.91160.com,    這個服務是供前端頁面調用;

 

近期發現,這2台伺服器的網路連接中,TIME_WAIT 數量差別很大,201的TIME_WAIT大概20000+,202的TIME_WAIT大概1000 ,差距20倍;2台的請求量差不多,都是以上內部調用的串連,且服務模式也沒有什麼差異,為什麼串連數會差這麼大?

 

後找原因:是因為這2個模組的調用程式由不同團隊寫的,調用方式不一樣,導致一個是調用方(用戶端,PHP程式)主動中斷連線,一個是被呼叫者(服務端 201、202)主動中斷連線;因TIME_WAIT 產生在主動中斷連線的一方,因此導致一台伺服器TIME_WAIT 數高,一台TIME_WAIT 數低;

 

這就有個細節,一次http請求,誰會先斷開TCP串連?什麼情況下用戶端先斷,什麼情況下服務端先斷?

百度後,找到原因,主要有http1.0和http1.1之間保持串連的差異以及http頭中connection、content-length、Transfer-encoding等參數有關;

 

 以下內容轉載:(http://blog.csdn.net/wangpengqi/article/details/17245349)

當然,在nginx中,對於http1.0與http1.1也是支援長串連的。什麼是長串連呢?我們知道,http請求是基於TCP協議之上的,那麼,當用戶端在發起請求前,需要先與服務端建立TCP串連,而每一次的TCP串連是需要三向交握來確定的,如果用戶端與服務端之間網路差一點,這三次互動消費的時間會比較多,而且三次互動也會帶來網路流量。當然,當串連斷開後,也會有四次的互動,當然對使用者體驗來說就不重要了。而http請求是請求應答式的,如果我們能知道每個要求標頭與響應體的長度,那麼我們是可以在一個串連上面執行多個請求的,這就是所謂的長串連,但前提條件是我們先得確定要求標頭與響應體的長度。對於請求來說,如果當前請求需要有body,如POST請求,那麼nginx就需要用戶端在要求標頭中指定content-length來表明body的大小,否則返回400錯誤。也就是說,請求體的長度是確定的,那麼響應體的長度呢?先來看看http協議中關於響應body長度的確定:
1.對於http1.0協議來說,如果回應標頭中有content-length頭,則以content-length的長度就可以知道body的長度了,用戶端在接收body時,就可以依照這個長度來接收資料,接收完後,就表示這個請求完成了。而如果沒有content-length頭,則用戶端會一直接收資料,直到服務端主動中斷連線,才表示body接收完了。
2.而對於http1.1協議來說,如果回應標頭中的Transfer-encoding為chunked傳輸,則表示body是流式輸出,body會被分成多個塊,每塊的開始會標識出當前塊的長度,此時,body不需要通過長度來指定。如果是非chunked傳輸,而且有content-length,則按照content-length來接收資料。否則,如果是非chunked,並且沒有content-length,則用戶端接收資料,直到服務端主動中斷連線。

從上面,我們可以看到,除了http1.0不帶content-length以及http1.1非chunked不帶content-length外,body的長度是可知的。此時,當服務端在輸出完body之後,會可以考慮使用長串連。能否使用長串連,也是有條件限制的。如果用戶端的要求標頭中的connection為close,則表示用戶端需要關掉長串連,如果為keep-alive,則用戶端需要開啟長串連,如果用戶端的請求中沒有connection這個頭,那麼根據協議,如果是http1.0,則預設為close,如果是http1.1,則預設為keep-alive。如果結果為keepalive,那麼,nginx在輸出完響應體後,會設定當前串連的keepalive屬性,然後等待用戶端下一次請求。當然,nginx不可能一直等待下去,如果用戶端一直不發資料過來,豈不是一直佔用這個串連?所以當nginx設定了keepalive等待下一次的請求時,同時也會設定一個最大等待時間,這個時間是通過選項keepalive_timeout來配置的,如果配置為0,則表示關掉keepalive,此時,http版本無論是1.1還是1.0,用戶端的connection不管是close還是keepalive,都會強製為close。

如果服務端最後的決定是keepalive開啟,那麼在響應的http頭裡面,也會包含有connection頭域,其值是”Keep-Alive”,否則就是”Close”。如果connection值為close,那麼在nginx響應完資料後,會主動關掉串連。所以,對於請求量比較大的nginx來說,關掉keepalive最後會產生比較多的time-wait狀態的socket。一般來說,當用戶端的一次訪問,需要多次訪問同一個server時,開啟keepalive的優勢非常大,比片伺服器,通常一個網頁會包含很多個圖片。開啟keepalive也會大量減少time-wait的數量。

 

總結: (不考慮keepalive)

http1.0  

帶content-length,body長度可知,用戶端在接收body時,就可以依據這個長度來接受資料。接受完畢後,就表示這個請求完畢了。用戶端主動調用close進入四次揮手。

不帶content-length ,body長度不可知,用戶端一直接受資料,直到服務端主動斷開

 

http1.1

帶content-length                       body長度可知     用戶端主動斷開

帶Transfer-encoding:chunked       body會被分成多個塊,每塊的開始會標識出當前塊的長度,body就不需要通過content-length來指定了。但依然可以知道body的長度 用戶端主動斷開

不帶Transfer-encoding:chunked且不帶content-length        用戶端接收資料,直到服務端主動中斷連線。

 

即 :如果能夠有辦法知道伺服器傳來的長度,都是用戶端首先斷開。如果不知道就一直接收資料。知道服務端斷開。

 

一次http請求,誰會先斷開TCP串連?什麼情況下用戶端先斷,什麼情況下服務端先斷?

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.