http、tcp的keepalive那些事兒

HTTP keep-alive

早期網頁比較簡單,一次http請求便可加載到全部資源。隨着網頁愈來愈複雜,每每須要屢次請求才能加載到全部資源,網頁上有css,html,圖片等各類資源,短期內須要屢次http請求。每次http請求都須要創建tcp鏈接、發送請求、接收請求、斷開鏈接等過程,很是耗系統資源.
css

能不能只創建一次http請求,同時請求css,html,圖片等資源?確定是不能的,由於http是無鏈接的,若是同一個http請求連續請求css,html,js,圖片等,返回的數據就不知道怎麼處理了,不知道返回的內容是哪次請求須要的。
html

那既然tcp鏈接是有狀態的,那能不能只創建一次tcp請求?畢竟tcp請求的握手和分手很是耗網絡資源,http請求只是對tcp報文的一個封裝,若是能複用tcp請求也能提高很多性能,答案是能夠的。
通常用戶進入一個網頁、瀏覽網頁須要一段時間,可是不會須要好久,所以http keep-alive通常不會設置太長,通常設置成1分鐘,即一分鐘以內對一個站點的訪問只會創建一個tcp鏈接,頁面上若是有多個http請求則會複用這個tcp鏈接。當沒有http請求時,一分鐘以後則斷開則會個tcp鏈接。
mysql

http keep-alive底層的tcp實際上是短連接,它是經過心跳機制着tcp鏈接不間斷
sql

http1.0默認是關閉的,經過http請求頭設置「connection: keep-alive」進行開啓;http1.1中默認開啓,經過http請求頭設置「connection: close」關閉
服務器

keep-alive機制:若開啓後,在一次http請求中,服務器進行響應後,再也不直接斷開TCP鏈接,而是將TCP鏈接維持一段時間。在這段時間內,若是同一客戶端再次向服務端發起http請求,即可以複用此TCP鏈接,向服務端發起請求,並重置timeout時間計數器,在接下來一段時間內還能夠繼續複用。這樣無疑省略了反覆建立和銷燬TCP鏈接的損耗。
markdown

http keep-alive是在服務端實現的,客戶端只是設置了一下http頭,加上keep-alive字段,服務端收到這個字段後不會立馬關閉tcp鏈接,會保持一個設置的時長,好比1分鐘,1分鐘以內若是有新的tcp請求則重置這個時間,不然關閉這個tcp鏈接。通常服務端會設置兩個參數:
網絡

  • maxKeepAliveRequests:一個鏈接上,最多能夠發起多少次請求,默認100,超過這個次數後會關閉。
  • keepAliveTimeout:底層socket鏈接最多保持多長時間,默認60秒,超過這個時間鏈接會被關閉。

通常的服務器端都會設置這兩個參數,供http keep-alive使用,客戶端只須要在http頭中開啓便可。
socket

TCP keepalive

tcp keepalive是tcp層面的長鏈接,它是真正的長鏈接,是傳輸層,這個tcp長鏈接可被上層全部協議使用,應用層協議對tcp的長鏈接無感知,並不直到tcp是長鏈接,只知道有可用的tcp鏈接而且使用便可。
tcp長鏈接默認是關閉的,須要開啓。它有三個參數:
tcp

  • 保活時間(tcp_keepalive_time)默認:7200秒
  • 保活時間間隔(tcp_keepalive_intvl)默認:75秒
  • 探測循環次數(tcp_keepalive_probes)默認:9次

也就是默認狀況下一條TCP鏈接在2小時(7200秒)都沒有報文交換後,會開始進行保活探測,若再通過9*75秒=11分鐘15秒的循環探測都未收到探測響應,即共計:2小時11分鐘15秒後會自動斷開TCP鏈接。
探測的結果可能有三種狀況:
微服務

  • 對方迴應了ACK。說明一切OK。若是接下來2小時尚未數據傳輸,那麼還會繼續發送keepalive探針,以確保鏈接存活。
  • 對方回覆RST,表示這個鏈接已經不存在。例如一方服務宕機後重啓,此時接收到探針,由於不存在對應的鏈接。
  • 沒有回覆。說明socket已經被關閉了

tcp的keepalive默認是關閉的,在建立鏈接的時候能夠經過參數設置打開。可是tcp的keepalive通常設置太長,不太實用,通常應用程序本身經過心跳機制來維持着長鏈接。即tcp建立的時候不設置keepalive,默認它永遠鏈接,它的斷開由應用程序主動關閉,只要應用程序不關閉這個tcp鏈接就不會被斷開。在複雜的網絡環境下,經過應用程序心跳機制來確保鏈接保持着通暢,實現應用層的長鏈接。這是現代不少應用層保持長鏈接經常使用的技巧,好比mysql,微服務,服務發現等。

區別

  • TCP鏈接每每就是咱們廣義理解上的長鏈接,由於它具有雙端連續收發報文的能力,tcp鏈接沒有長短之分,它只要創建起來了就會永遠鏈接着,除非主動分手,可是因爲網絡問題,可能有一端會斷開鏈接,這個時候另一端若是不感知,則會長時間維持着這個無效的鏈接。因此爲了減小無效鏈接的維護,設置一個keepalive;開啓了keep-alive的HTTP鏈接,也是一種長鏈接,可是它因爲協議自己的限制,服務端沒法主動發起應用報文。若是一個http請求結束,立刻關閉tcp鏈接或者長時間不關閉tcp鏈接,對系統資源都是一種消耗,所以設置一個keep-alive,讓這個tcp鏈接在一段時間內保持着鏈接狀態不要關閉,而這個時間長度是由服務器設置的。
  • TCP中的keepalive是用來保鮮、保活的,tcp原本就是長鏈接,須要主動關閉纔會斷開。爲了監聽對方是否網絡一般才設置一個keepalive;HTTP中的keep-alive機制主要爲了讓支撐它的TCP鏈接活的的更久,因此一般又叫作:HTTP persistent connection(持久鏈接) 和 HTTP connection reuse(鏈接重用)

參考

【1】HTTP keep-alive和TCP keepalive的區別,你瞭解嗎?
【2】詳解HTTP 與TCP中Keep-Alive機制的區別

相關文章
相關標籤/搜索