天天看點

HTTP keep-alive和TCP keepalive的差別,你了解嗎?一、簡介二、TCP keepalive三、HTTP keep-alive四、總結五、彩蛋

HTTP keep-alive和TCP keepalive的差別

文章目錄

  • 一、簡介
    • 1.1、TCP協定簡介
    • 1.2、HTTP協定簡介
  • 二、TCP keepalive
    • 2.1、簡介
    • 2.2、實驗
    • 2.3、擴充
  • 三、HTTP keep-alive
    • 3.1、簡介
    • 3.2、實驗
      • 3.2.1、實驗一:禁用keep-alive的http請求
      • 3.2.2、實驗二:啟用keep-alive的http請求
    • 3.3、擴充
  • 四、總結
  • 五、彩蛋

1、從文中找出我的IP

2、http請求中是客服端還是服務端主動關閉的tcp連接配接?

請閱讀到最後的彩蛋部分

HTTP和TCP都是老生常談的知識點,本文不進行鋪開贅述。我們可能在HTTP和TCP中都聽說“長連接配接”的說法,也聽過HTTP中有keep-alive,TCP中有keepalive。那麼,HTTP和TCP的長連接配接有何差別?HTTP中的keep-alive和TCP中keepalive又有什麼差別?

Tips:HTTP中是keep-alive,TCP中是keepalive,HTTP中是帶中劃線的。大小寫無所謂。

一、簡介

HTTP keep-alive和TCP keepalive的差別,你了解嗎?一、簡介二、TCP keepalive三、HTTP keep-alive四、總結五、彩蛋

上面是我先前做TCP協定分享時整理的一張表格,從上面可以看出:不管是在OSI七層網絡模型還是在TCP/IP五層網絡模型中,TCP是傳輸層的一種協定,而HTTP是應用層的一種協定。

HTTP和TCP的理論和實作還是相當複雜的,下面隻簡單介紹和本文主題相關的知識點。

1.1、TCP協定簡介

TCP協定也叫傳輸控制協定(TCP,Transmission Control Protocol)是一種面向連接配接的、可靠的、基于位元組流的傳輸層通信協定。使用TCP的兩個程式(用戶端和服務端)在交換資料前,通過三次握手來建立TCP連接配接,建立連接配接後就可以進行基于位元組流的雙工通訊,由TCP内部實作保證通訊的可靠性,完全通訊完成後,通過四次揮手斷開連接配接。

在用戶端和服務端間的網絡一切正常、且雙方都沒主動發起關閉連接配接的請求時,此TCP連接配接理論上可以永久保持。但是,網絡情況是及其複雜的,在雙方長時間未通訊時,如何得知對方還活着?如何得知這個TCP連接配接是健康且具有通訊能力的?

1.2、HTTP協定簡介

HTTP協定是Hyper Text Transfer Protocol(超文本傳輸協定)的縮寫。HTTP是網際網路的資料通信的基礎。HTTP是一個應用層協定,通常運作在TCP協定之上。它由請求和響應構成,是一個标準的用戶端伺服器模型(C/S模型)。HTTP是一個無狀态的協定。

無狀态怎麼解釋?HTTP協定永遠都是用戶端發起請求,伺服器回送響應。每次連接配接隻處理一個請求,當伺服器傳回本次請求的應答後便立即關閉連接配接,下次請求用戶端再重建立立連接配接。也就無法實作在用戶端沒有發起請求的時候,伺服器主動将消息推送給用戶端。

HTTP協定運作在TCP協定之上,它無狀态會導緻用戶端的每次請求都需要重建立立TCP連接配接,接受到服務端響應後,斷開TCP連接配接。對于每次建立、斷開TCP連接配接,還是有相當的性能損耗的。那麼,如何才能盡可能的減少性能損耗呢?

二、TCP keepalive

2.1、簡介

正如上面提出的問題:在雙方長時間未通訊時,如何得知對方還活着?如何得知這個TCP連接配接是健康且具有通訊能力的?

TCP的保活機制就是用來解決此類問題,這個機制我們也可以稱作:keepalive。保活機制預設是關閉的,TCP連接配接的任何一方都可打開此功能。有三個主要配置參數用來控制保活功能。

如果在一段時間(保活時間:tcp_keepalive_time)内此連接配接都不活躍,開啟保活功能的一端會向對端發送一個保活探測封包。

  • 若對端正常存活,且連接配接有效,對端必然能收到探測封包并進行響應。此時,發送端收到響應封包則證明TCP連接配接正常,重置保活時間計數器即可。
  • 若由于網絡原因或其他原因導緻,發送端無法正常收到保活探測封包的響應。那麼在一定**探測時間間隔(tcp_keepalive_intvl)後,将繼續發送保活探測封包。直到收到對端的響應,或者達到配置的探測循環次數上限(tcp_keepalive_probes)**都沒有收到對端響應,這時對端會被認為不可達,TCP連接配接随存在但已失效,需要将連接配接做中斷處理。

在探測過程中,對端主機會處于以下四種狀态之一:

狀态 處理
對方主機仍在工作,并且可達 TCP連接配接正常,将保活計時器重置。
對方主機已崩潰,包括:已關閉或者正在重新開機 TCP連接配接不正常,經過指定次數的探測依然沒得到響應,則斷開連接配接
對方主機崩潰并且已經重新開機 重新開機後原連接配接已失效,對方由于不認識探測封包,會響應重置封包段,請求端将連接配接斷開
對方主機仍在工作,但由于某些原因不可達(如:網絡原因) TCP連接配接不正常,經過指定次數的探測依然沒得到響應,則斷開連接配接

2.2、實驗

這裡,強烈推薦《TCP/IP詳解 卷1:協定》的第二版(這裡一定是第二版), 第17章:TCP保活機制。這裡建議17章都看,17.1和17.2小節就涵蓋了我上面介紹的内容。

17.2.1 小節中還通過實驗的方式詳細驗證了“對端主機會處于以下四種狀态”以及對于這四種狀态TCP都是如何去處理。

這本書中的實驗已經比較通俗易懂了,我暫且沒有親自動手去模拟實踐,後續時間充足,會親自動手進行實驗。

2.3、擴充

上面提到了三個參數保活時間:tcp_keepalive_time、探測時間間隔:tcp_keepalive_intvl、探測循環次數:tcp_keepalive_probes。

這三個參數,在linux上可以在

/proc/sys/net/ipv4/

路徑下找到,或者通過

sysctl -a | grep keepalive

指令檢視目前核心運作參數。

[[email protected] ~]# cd /proc/sys/net/ipv4
[[email protected] ipv4]# pwd
/proc/sys/net/ipv4
[[email protected] ipv4]# cat /proc/sys/net/ipv4/tcp_keepalive_time
7200
[[email protected] ipv4]# cat /proc/sys/net/ipv4/tcp_keepalive_probes
9
[[email protected] ipv4]# cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75
[[email protected] ipv4]# sysctl -a | grep keepalive
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
           
  • 保活時間(tcp_keepalive_time)預設:7200秒
  • 保活時間間隔(tcp_keepalive_intvl)預設:75秒
  • 探測循環次數(tcp_keepalive_probes)預設:9次

也就是預設情況下一條TCP連接配接在2小時(7200秒)都沒有封包交換後,會開始進行保活探測,若再經過9*75秒=11分鐘15秒的循環探測都未收到探測響應,即共計:2小時11分鐘15秒後會自動斷開TCP連接配接。

别走開,還有一個騷操作

Linux平台下我們還可以借助

man

指令檢視TCP協定的一些描述和參數定義。下面兩個指令的效果相同:

  • 指令一:

    man tcp

  • 指令二:

    man 7 tcp

7的含義是:

man

指令使用手冊共9章,TCP的幫助手冊位于第7章。不知道在第幾章也無所謂,使用

man tcp

也可,彈出的手冊左上角也有寫第幾章。(

man ls

等同于

man 1 ls

man ip

等同于

man 8 ip

,可以自己嘗試使用 )。

下面我們看下

man tcp

下的和我們本文有關的幾個點:

HTTP keep-alive和TCP keepalive的差別,你了解嗎?一、簡介二、TCP keepalive三、HTTP keep-alive四、總結五、彩蛋
HTTP keep-alive和TCP keepalive的差別,你了解嗎?一、簡介二、TCP keepalive三、HTTP keep-alive四、總結五、彩蛋
HTTP keep-alive和TCP keepalive的差別,你了解嗎?一、簡介二、TCP keepalive三、HTTP keep-alive四、總結五、彩蛋

上面介紹的三個參數tcp_keepalive_time、tcp_keepalive_intvl、tcp_keepalive_probes都是系統級别的,針對整個系統生效。下面介紹針對單條Socket連接配接細粒度設定的三個選項參數:保活時間:TCP_KEEPIDLE、保活探測時間間隔:TCP_KEEPINTVL、探測循環次數:TCP_KEEPCNT

HTTP keep-alive和TCP keepalive的差別,你了解嗎?一、簡介二、TCP keepalive三、HTTP keep-alive四、總結五、彩蛋
HTTP keep-alive和TCP keepalive的差別,你了解嗎?一、簡介二、TCP keepalive三、HTTP keep-alive四、總結五、彩蛋

在我們的Netty的架構中可以看到針對Socket選項的配置,如使用epoll的IO模型中

EpollSocketChannelConfig

類中的配置:

HTTP keep-alive和TCP keepalive的差別,你了解嗎?一、簡介二、TCP keepalive三、HTTP keep-alive四、總結五、彩蛋

更多細節,等你挖掘。

三、HTTP keep-alive

3.1、簡介

HTTP協定簡介中提到http協定是一個運作在TCP協定之上的無狀态的應用層協定。它的特點是:用戶端的每一次請求都要和服務端建立TCP連接配接,伺服器響應後,斷開TCP連接配接。下次用戶端再有請求,則重建立立連接配接。

在早期的http1.0中,預設就是上述介紹的這種“請求-應答”模式。這種方式頻繁的建立連接配接和銷毀連接配接無疑是有一定性能損耗的。

是以引入了keep-alive機制。http1.0預設是關閉的,通過http請求頭設定“connection: keep-alive”進行開啟;http1.1中預設開啟,通過http請求頭設定“connection: close”關閉。

keep-alive機制:若開啟後,在一次http請求中,伺服器進行響應後,不再直接斷開TCP連接配接,而是将TCP連接配接維持一段時間。在這段時間内,如果同一用戶端再次向服務端發起http請求,便可以複用此TCP連接配接,向服務端發起請求,并重置timeout時間計數器,在接下來一段時間内還可以繼續複用。這樣無疑省略了反複建立和銷毀TCP連接配接的損耗。

3.2、實驗

下面用兩組實驗證明HTTP keep-alive的存在。

實驗工具:Wireshark

用戶端IP:*.*.3.52

服務端IP:*.*.17.254

3.2.1、實驗一:禁用keep-alive的http請求

HTTP keep-alive和TCP keepalive的差別,你了解嗎?一、簡介二、TCP keepalive三、HTTP keep-alive四、總結五、彩蛋

從上圖請求清單區中,我們可以發現:

  • 106、107、108三個請求是TCP建立連接配接三次握手的請求
  • 109、110兩個請求分别是:http的請求封包和http的響應封包
  • 111、112、120、121這四個請求是TCP斷開連接配接四次揮手的請求

(由于一台機器上網絡請求較多,我加了篩選條件,僅顯示用戶端和服務端通信的網絡請求,是以請求的序号是不連續的)

從上圖中間的請求資料解析區,可以确定:此次http請求的請求頭中有“Connection: close”,即keep-alive是關閉的。

結論:禁用keep-alive的http請求時,會先建立TCP連接配接,然後發送封包、響應封包、最後斷開TCP連接配接。

3.2.2、實驗二:啟用keep-alive的http請求

HTTP keep-alive和TCP keepalive的差別,你了解嗎?一、簡介二、TCP keepalive三、HTTP keep-alive四、總結五、彩蛋
HTTP keep-alive和TCP keepalive的差別,你了解嗎?一、簡介二、TCP keepalive三、HTTP keep-alive四、總結五、彩蛋

這次實驗請求較多,一張圖放不下,兩張圖是連續的,圖1的第二塊綠色區域和圖2的第一塊綠色區域是重疊的(注意看第一列的No.編号)

先說下我的操作:

  1. 開啟keep-alive前提下發起第一次http請求
  2. 7秒左右時,同樣的機器同樣的http請求,再重新調用一次

我們根據圖中抓包,分析下網絡請求:

  • 197、198、199請求:三次握手建立TCP建立連接配接
  • 200、203請求:http的請求封包和http的響應封包
  • 212請求:可以通過Protocol列看到它是一條TCP封包。我的了解是:在keep-alive這種機制下,用戶端收到服務端響應封包後,需要告知服務端“已收到”。由于要複用TCP連接配接,是以會多一層保障機制,類似TCP的握手和揮手
  • 459-1965請求(圖1中的第一塊黑色區域中):6秒内(第二列代表Time),每隔1秒,發生一對TCP請求的來回,用來維護TCP連接配接的可用性。保證和等待該TCP連接配接被複用
  • 1743、1744、1745、1755請求:其中的1743和1745是我第二次發起http請求的請求封包和響應封包。1744請求是:用戶端發起請求時,服務端先回複用戶端“已收到,馬上處理”。緊接着1745将結果響應給用戶端。1755則是用戶端收到響應後,回複服務端“已收到響應,多謝”。
  • 2028-3903請求:10秒内,每隔1秒,發生一對TCP請求的來回,用來維護TCP連接配接的可用性。保證和等待該TCP連接配接被複用
  • 4127-4131請求:10秒内我沒再發起http請求,四次揮手斷開TCP連接配接。長時間沒被複用,也沒必要一直維持下去,浪費資源,還可能造成網絡擁堵。

注意:10秒無請求,TCP連接配接在斷開,10秒也不是預設的,隻是環境的配置。是Httpd守護程序,提供的keep-alive timeout時間設定參數。比如nginx的keepalive_timeout,和Apache的KeepAliveTimeout。

3.3、擴充

HTTP keep-alive和TCP keepalive的差別,你了解嗎?一、簡介二、TCP keepalive三、HTTP keep-alive四、總結五、彩蛋

其實對于HTTP keep-alive機制可以總結為上圖所示。

啟用HTTP keep-Alive的優缺點:

優點:keep-alive機制避免了頻繁建立和銷毀連接配接的開銷。 同時,減少服務端TIME_WAIT狀态的TCP連接配接的數量(因為由服務端程序主動關閉連接配接)

缺點:若keep-alive timeout設定的時間較長,長時間的TCP連接配接維持,會一定程度的浪費系統資源。

總體而言,HTTP keep-Alive的機制還是利大于弊的,隻要合理使用、配置合理的timeout參數。

四、總結

回到文章開頭提出的問題:HTTP和TCP的長連接配接有何差別?HTTP中的keep-alive和TCP中keepalive又有什麼差別?

1、TCP連接配接往往就是我們廣義了解上的長連接配接,因為它具備雙端連續收發封包的能力;開啟了keep-alive的HTTP連接配接,也是一種長連接配接,但是它由于協定本身的限制,服務端無法主動發起應用封包。

2、TCP中的keepalive是用來保鮮、保活的;HTTP中的keep-alive機制主要為了讓支撐它的TCP連接配接活的的更久,是以通常又叫做:HTTP persistent connection(持久連接配接) 和 HTTP connection reuse(連接配接重用)。

五、彩蛋

彩蛋一

你能從文中找出我在HTTP keep-alive實驗中用戶端和服務端的完整IP嗎?

如能找出,說明對網絡協定的了解已如火純青。

彩蛋二

在HTTP請求中,到底是「服務端」還是「用戶端」主動關閉連接配接呢?

看到過很多文章,有人說服務端、有人說用戶端、有人說分情況(keep-alive的開啟與否)既可能是用戶端也可能是服務端。你信誰?最後翻來覆去發現各個網站的各種文章基本類似,隻有觀點,沒有論據。

HTTP keep-alive章節的實驗結果:無論開啟keep-alive與否,最終由服務端主動斷開TCP連接配接。

但是我給出問題的答案是:通常由服務端主動關閉連接配接。沒有寫“肯定由服務端主動關閉連接配接”的原因是,我沒遇到用戶端主動關閉連接配接的場景,并不代表沒有。網絡和協定博大精深,等待我們繼續去探索。

這個彩蛋的目的由兩個:

1、告訴大家:網上的文章、他人的觀點,還是要思辨的看待。

2、我确實想知道什麼情況下,用戶端主動關閉連接配接?歡迎大家私信讨論,一定要有真憑實據

彩蛋三

  • Wireshark是一款功能強大的網絡封包分析可視化軟體。《TCP/IP詳解 卷1:協定》第二版相比第一版,書中的抓包工具也将tcpdump改為****Wireshark。****
  • 個人觀點:《TCP/IP詳解 卷1:協定》第一版和第二版結合起來看效果更好。第一版的TCP阻塞控制将的更通俗易懂,第二版的TCP保活機制講的更清晰。

繼續閱讀