淺談Http長連接和Keep-Alive以及Tcp的Keepalive


原文:https://blog.csdn.net/weixin_37672169/article/details/80283935 

Keep-Alive模式:
我們知道Http協議采用“請求-應答”模式,當使用普通模式,即非Keep-Alive模式時,每個請求/應答,客戶端和服務器都要新建一個連接,完成之后立即斷開連接;當使用Keep-Alive模式時,Keep-Alive功能使客戶端到服務器端的連接持續有效,當出現對服務器的后繼請求時,Keep-Alive功能避免了建立或者重新建立連接。
http1.0中默認是關閉的,需要在http頭加入”Connection: Keep-Alive”,才能啟用Keep-Alive;
http 1.1中默認啟用Keep-Alive,如果加入”Connection: close “才關閉。目前大部分瀏覽器都是用http1.1協議,也就是說默認都會發起Keep-Alive的連接請求了,所以是否能完成一個完整的Keep- Alive連接就看服務器設置情況。下圖是普通模式和長連接模式的請求對比:

 


開啟Keep-Alive的優缺點:
優點:Keep-Alive模式更加高效,因為避免了連接建立和釋放的開銷。
缺點:長時間的Tcp連接容易導致系統資源無效占用,浪費系統資源。

當保持長連接時,如何判斷一次請求已經完成?
Content-Length
Content-Length表示實體內容的長度。瀏覽器通過這個字段來判斷當前請求的數據是否已經全部接收。
所以,當瀏覽器請求的是一個靜態資源時,即服務器能明確知道返回內容的長度時,可以設置Content-Length來控制請求的結束。但當服務器並不知道請求結果的長度時,如一個動態的頁面或者數據,Content-Length就無法解決上面的問題,這個時候就需要用到Transfer-Encoding字段。

Transfer-Encoding
Transfer-Encoding是指傳輸編碼,在上面的問題中,當服務端無法知道實體內容的長度時,就可以通過指定Transfer-Encoding: chunked來告知瀏覽器當前的編碼是將數據分成一塊一塊傳遞的。當然, 還可以指定Transfer-Encoding: gzip, chunked表明實體內容不僅是gzip壓縮的,還是分塊傳遞的。最后,當瀏覽器接收到一個長度為0的chunked時, 知道當前請求內容已全部接收。

Keep-Alive timeout:
Httpd守護進程,一般都提供了keep-alive timeout時間設置參數。比如nginx的keepalive_timeout,和Apache的KeepAliveTimeout。這個keepalive_timout時間值意味着:一個http產生的tcp連接在傳送完最后一個響應后,還需要hold住keepalive_timeout秒后,才開始關閉這個連接。
當httpd守護進程發送完一個響應后,理應馬上主動關閉相應的tcp連接,設置 keepalive_timeout后,httpd守護進程會想說:”再等等吧,看看瀏覽器還有沒有請求過來”,這一等,便是keepalive_timeout時間。如果守護進程在這個等待的時間里,一直沒有收到瀏覽器發過來http請求,則關閉這個http連接。

Tcp的Keepalive:
連接建立之后,如果客戶端一直不發送數據,或者隔很長時間才發送一次數據,當連接很久沒有數據報文傳輸時如何去確定對方還在線,到底是掉線了還是確實沒有數據傳輸,連接還需不需要保持,這種情況在TCP協議設計中是需要考慮到的。
TCP協議通過一種巧妙的方式去解決這個問題,當超過一段時間之后,TCP自動發送一個數據為空的報文(偵測包)給對方,如果對方回應了這個報文,說明對方還在線,連接可以繼續保持,如果對方沒有報文返回,並且重試了多次之后則認為鏈接丟失,沒有必要保持連接。

tcp keep-alive是TCP的一種檢測TCP連接狀況的保鮮機制。tcp keep-alive保鮮定時器,支持三個系統內核配置參數:
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_time = 1800
keepalive是TCP保鮮定時器,當網絡兩端建立了TCP連接之后,閑置(雙方沒有任何數據流發送往來)了tcp_keepalive_time后,服務器就會嘗試向客戶端發送偵測包,來判斷TCP連接狀況(有可能客戶端崩潰、強制關閉了應用、主機不可達等等)。如果沒有收到對方的回答(ack包),則會在 tcp_keepalive_intvl后再次嘗試發送偵測包,直到收到對方的ack,如果一直沒有收到對方的ack,一共會嘗試 tcp_keepalive_probes次,每次的間隔時間在這里分別是15s, 30s, 45s, 60s, 75s。如果嘗試tcp_keepalive_probes,依然沒有收到對方的ack包,則會丟棄該TCP連接。TCP連接默認閑置時間是2小時,一般設置為30分鍾足夠了。


免責聲明!

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



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