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


一次性說清楚秒驗(本機號碼一鍵登錄)

2021-03-02

技術總監面試,提問:Redis熱點key解決方案

2021-02-28

【性能測試】輕量級壓測工具Hey

2021-02-23


 我們知道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分鐘足夠了。

回覆乾貨獲取精選乾貨視頻教程
回覆加羣加入疑難問題攻堅交流羣
回覆mat獲取內存溢出問題分析詳細文檔教程
回覆賺錢獲取用java寫一個能賺錢的微信機器人
回覆副業獲取程序員副業攻略一份


戳這兒


本文分享自微信公衆號 - 俠夢的開發筆記(xmdevnote)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章