Keepalive詳解

https://www.jianshu.com/p/9fe2c140fa52css

什麼是KeepAlive?

首先,咱們要明確咱們談的是TCPKeepAlive 仍是HTTPKeep-Alive。TCP的KeepAlive和HTTP的Keep-Alive是徹底不一樣的概念,不能混爲一談。實際上HTTP的KeepAlive寫法是Keep-Alive,跟TCP的KeepAlive寫法上也有不一樣。面試

  • TCP的keepalive是側重在保持客戶端和服務端的鏈接,一方會不按期發送心跳包給另外一方,當一方端掉的時候,沒有斷掉的定時發送幾回心跳包,若是間隔發送幾回,對方都返回的是RST,而不是ACK,那麼就釋放當前連接。設想一下,若是tcp層沒有keepalive的機制,一旦一方斷開鏈接卻沒有發送FIN給另一方的話,那麼另一方會一直覺得這個鏈接仍是存活的,幾天,幾月。那麼這對服務器資源的影響是很大的。瀏覽器

  • HTTP的keep-alive通常咱們都會帶上中間的橫槓,普通的http鏈接是客戶端鏈接上服務端,而後結束請求後,由客戶端或者服務端進行http鏈接的關閉。下次再發送請求的時候,客戶端再發起一個鏈接,傳送數據,關閉鏈接。這麼個流程反覆。可是一旦客戶端發送connection:keep-alive頭給服務端,且服務端也接受這個keep-alive的話,兩邊對上暗號,這個鏈接就能夠複用了,一個http處理完以後,另一個http數據直接從這個鏈接走了。減小新建和斷開TCP鏈接的消耗。服務器

兩者的做用簡單來講:網絡

HTTP協議的Keep-Alive意圖在於短期內鏈接複用,但願能夠短期內在同一個鏈接上進行屢次請求/響應。負載均衡

TCP的KeepAlive機制意圖在於保活、心跳,檢測鏈接錯誤。當一個TCP鏈接兩端長時間沒有數據傳輸時(一般默認配置是2小時),發送keepalive探針,探測連接是否存活。運維

總之,記住HTTP的Keep-Alive和TCP的KeepAlive不是一回事。異步

tcp的keepalive是在ESTABLISH狀態的時候,雙方如何檢測鏈接的可用行。而http的keep-alive說的是如何避免進行重複的TCP三次握手和四次揮手的環節。socket


TCP的KeepAlive

1.爲何要有KeepAlive?tcp

在談KeepAlive以前,咱們先來了解下簡單TCP知識(知識很簡單,高手直接忽略)。首先要明確的是在TCP層是沒有「請求」一說的,常常聽到在TCP層發送一個請求,這種說法是錯誤的。

TCP是一種通訊的方式,「請求」一詞是事務上的概念,HTTP協議是一種事務協議,若是說發送一個HTTP請求,這種說法就沒有問題。也常常聽到面試官反饋有些面試運維的同窗,基本的TCP三次握手的概念不清楚,面試官問TCP是如何創建連接,面試者上來就說,假如我是客戶端我發送一個請求給服務端,服務端發送一個請求給我。。。

這種一聽就知道對TCP基本概念不清楚。下面是我經過wireshark抓取的一個TCP創建握手的過程。(命令行基本上用TCPdump,後面咱們還會用這張圖說明問題):

 
TCP抓包

如今我看只要看前3行,這就是TCP三次握手的完整創建過程,第一個報文SYN從發起方發出,第二個報文SYN,ACK是從被鏈接方發出,第三個報文ACK確認對方的SYN,ACK已經收到,以下圖:

 
TCP創建鏈接過程

可是數據實際上並無傳輸,請求是有數據的,第四個報文才是數據傳輸開始的過程,細心的讀者應該可以發現wireshark把第四個報文解析成HTTP協議,HTTP協議的GET方法和URI也解析出來,因此說TCP層是沒有請求的概念,HTTP協議是事務性協議纔有請求的概念,TCP報文承載HTTP協議的請求(Request)和響應(Response)。

如今纔是開始說明爲何要有KeepAlive。連接創建以後,若是應用程序或者上層協議一直不發送數據,或者隔很長時間才發送一次數據,當連接好久沒有數據報文傳輸時如何去肯定對方還在線,究竟是掉線了仍是確實沒有數據傳輸,連接還需不須要保持,這種狀況在TCP協議設計中是須要考慮到的。

TCP協議經過一種巧妙的方式去解決這個問題,當超過一段時間以後,TCP自動發送一個數據爲空的報文給對方,若是對方迴應了這個報文,說明對方還在線,連接能夠繼續保持,若是對方沒有報文返回,而且重試了屢次以後則認爲連接丟失,沒有必要保持連接。

2.怎麼開啓KeepAlive?

KeepAlive並非默認開啓的,在Linux系統上沒有一個全局的選項去開啓TCP的KeepAlive。須要開啓KeepAlive的應用必須在TCP的socket中單獨開啓。Linux Kernel有三個選項影響到KeepAlive的行爲:

  • tcp_keepalive_time 7200// 距離上次傳送數據多少時間未收到新報文判斷爲開始檢測,單位秒,默認7200s
  • tcp_keepalive_intvl 75// 檢測開始每多少時間發送心跳包,單位秒,默認75s
  • tcp_keepalive_probes 9// 發送幾回心跳包對方未響應則close鏈接,默認9次

TCP socket也有三個選項和內核對應,經過setsockopt系統調用針對單獨的socket進行設置:

  • TCPKEEPCNT: 覆蓋 tcpkeepaliveprobes
  • TCPKEEPIDLE: 覆蓋 tcpkeepalivetime
  • TCPKEEPINTVL: 覆蓋 tcpkeepalive_intvl

舉個例子,以個人系統默認設置爲例,kernel默認設置的tcpkeepalivetime是7200s, 若是我在應用程序中針對socket開啓了KeepAlive,而後設置的TCP_KEEPIDLE爲60,那麼TCP協議棧在發現TCP連接空閒了60s沒有數據傳輸的時候就會發送第一個探測報文。

3. 須要注意,KeepAlive的不足和侷限性

其實,tcp自帶的keepalive仍是有些不足之處的。

keepalive只能檢測鏈接是否存活,不能檢測鏈接是否可用。例如,某一方發生了死鎖,沒法在鏈接上進行任何讀寫操做,可是操做系統仍然能夠響應網絡層keepalive包。

TCP keepalive 機制依賴於操做系統的實現,靈活性不夠,默認關閉,且默認的 keepalive 心跳時間是 兩個小時, 時間較長。

代理(如socks proxy)、或者負載均衡器,會讓tcp keep-alive失效

基於此,咱們旺旺須要加上應用層的心跳。這個須要本身實現,這裏就不展開了。


HTTP的Keep-Alive

1. HTTP爲何須要Keep-Alive?

一般一個網頁可能會有不少組成部分,除了文本內容,還會有諸如:js、css、圖片等靜態資源,有時還會異步發起AJAX請求。只有全部的資源都加載完畢後,咱們看到網頁完整的內容。然而,一個網頁中,可能引入了幾十個js、css文件,上百張圖片,若是每請求一個資源,就建立一個鏈接,而後關閉,代價實在太大了。

基於此背景,咱們但願鏈接可以在短期內獲得複用,在加載同一個網頁中的內容時,儘可能的複用鏈接,這就是HTTP協議中keep-alive屬性的做用。

  • HTTP的Keep-Alive是HTTP1.1默認開啓的功能。經過headers設置"Connection: close "關閉
  • 在HTTP1.0中是默認關閉的。經過headers設置"Connection: Keep-Alive"開啓。

對於客戶端來講,不管是瀏覽器,仍是手機App,或者咱們直接在Java代碼中使用HttpUrlConnection,只是負責在請求頭中設置Keep-Alive。Keep-Alive屬性保持鏈接的時間長短是由服務端決定的,一般配置都是在幾十秒左右。

TCP鏈接創建以後,HTTP協議使用TCP傳輸HTTP協議的請求(Request)和響應(Response)數據,一次完整的HTTP事務以下圖:

 
 
HTTP請求
 

這張圖我簡化了HTTP(Req)和HTTP(Resp),實際上的請求和響應須要多個TCP報文。
從圖中能夠發現一個完整的HTTP事務,有連接的創建,請求的發送,響應接收,斷開連接這四個過程,早期經過HTTP協議傳輸的數據以文本爲主,一個請求可能就把全部要返回的數據取到,可是,如今要展示一張完整的頁面須要不少個請求才能完成,如圖片.JS.CSS等,若是每個HTTP請求都須要新建並斷開一個TCP,這個開銷是徹底沒有必要的。

開啓HTTP Keep-Alive以後,能複用已有的TCP連接,當前一個請求已經響應完畢,服務器端沒有當即關閉TCP連接,而是等待一段時間接收瀏覽器端可能發送過來的第二個請求,一般瀏覽器在第一個請求返回以後會當即發送第二個請求,若是某一時刻只能有一個連接,同一個TCP連接處理的請求越多,開啓KeepAlive能節省的TCP創建和關閉的消耗就越多。

固然一般會啓用多個連接去從服務器器上請求資源,可是開啓了Keep-Alive以後,仍然能加快資源的加載速度。HTTP/1.1以後默認開啓Keep-Alive, 在HTTP的頭域中增長Connection選項。當設置爲Connection:keep-alive表示開啓,設置爲Connection:close表示關閉。

做者:Katou_Megumi 連接:https://www.jianshu.com/p/9fe2c140fa52 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索