keepalive 原理講解


keepalive

我們說到keepalive的時候,需要先明確一點,這個keepalive說的是tcp的還是http的。

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

http的keep-alive一般我們都會帶上中間的橫杠,普通的http連接是客戶端連接上服務端,然后結束請求后,由客戶端或者服務端進行http連接的關閉。下次再發送請求的時候,客戶端再發起一個連接,傳送數據,關閉連接。這么個流程反復。但是一旦客戶端發送connection:keep-alive頭給服務端,且服務端也接受這個keep-alive的話,兩邊對上暗號,這個連接就可以復用了,一個http處理完之后,另外一個http數據直接從這個連接走了。

tcp層的keepalive

tcp的keepalive就是為了檢測鏈接的可用性。主要調節的參數有三個:

  • tcp_keepalive_time // 距離上次傳送數據多少時間未收到判斷為開始檢測
  • tcp_keepalive_intvl // 檢測開始每多少時間發送心跳包
  • tcp_keepalive_probes // 發送幾次心跳包對方未響應則close連接

基本上的流程:

在客戶端和服務端進行完三次握手之后,客戶端和服務端都處在ESTABLISH狀態,這個時候進行正常的PSH和ACK交互,但是一旦一方服務中斷了,另一方在距離上次PSH時間tcp_keepalive_time發現對方未發送數據,則開始心跳檢測。心跳檢測實際就是發送一個PSH的空心跳包,這里說的空心跳包就是包的數據為空,但是TCP包的頭部的數據和標識和正常包一樣。如果這個包獲取到的是RST返回的話,下面就會繼續每隔tcp_keepalive_intval的時長發送一個空心跳包,如果tcp_keepalive_probes次心跳包對方都是返回RST而不是ACK,則心跳發起方就判斷這個連接已經失效,主動CLOST這個連接。

這三個參數可以每個TCP連接都不同,使用tcp設置變量的函數可以設置當前tcp連接的這三個對應的值。

int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)

tcp層的keepalive會在兩個場景下比較有用

檢測連接的一方是否斷了

這里說的連接的一方是否斷了包含幾種情況:

  • 連接一方服務中止
  • 網絡不好導致的服務長時間無響應
  • 連接一方服務重啟中

結合這三種方式就很好理解為什么會有 tcp_keepalive_time, tcp_keepalive_intval, tcp_keepalive_probes三種的設置了。如果是對方服務器進行重啟的時候,我們不能根據一次的tcp返回重置信號就判定這個連接失效。相反的,重啟之后,這個心跳包一旦正常,這個連接仍然可以繼續使用。

防止因為長時間不用鏈接導致連接失效

這個往往在代理或者內網狀況下會使用到。一般NAT網絡為了資源,會和外網保持一定的資源連接數,而且采用的是淘汰機制,淘汰掉舊的,不用的連接,創建和使用新的連接。如果我們沒有心跳檢測機制,那么我們的連接在一段時間沒有使用的時候,NAT對外的機制會判斷對應的對外網絡是無用的,淘汰掉舊的,即使這個時候客戶端和服務端都還正常服務着,只是長時間未聯絡了而已。keepalive的機制由於有定時心跳包,自然就能解決這個問題了。

http層的keep-alive

http層有個keep-alive, 它主要是用於客戶端告訴服務端,這個連接我還會繼續使用,在使用完之后不要關閉。

這個設置會影響web服務的哪幾個方面呢?

性能

這個設置首先會在性能上對客戶端和服務器端性能上有一定的提升。很好理解的是少了TCP的三次握手和四次揮手,第二次傳遞數據就可以通過前一個連接直接進行數據交互了。當然會提升服務性能了。

服務器TIME_WAIT的時間

由於HTTP服務的發起方一般都是瀏覽器,即客戶端。但是先執行完邏輯,傳輸完數據的一定是服務端。那么一旦沒有keep-alive機制,服務端在傳送完數據之后會率先發起連接斷開的操作。由於TCP的四次揮手機制,先發起連接斷開的一方會在連接斷開之后進入到TIME_WAIT的狀態達到2MSL之久。設想,如果沒有開啟HTTP的keep-alive,那么這個TIME_WAIT就會留在服務端,由於服務端資源是非常有限的,我們當然傾向於服務端不會同一時間hold住過多的連接,這種TIME_WAIT的狀態應該盡量在客戶端保持。那么這個http的keep-alive機制就起到非常重要的作用了。

所以

基本上基於這兩個原因,現在的瀏覽器發起web請求的時候,都會帶上connection:keep-alive的頭了。

總結

TCP的keepalive機制和HTTP的keep-alive機制是說的完全不同的兩個東西,tcp的keepalive是在ESTABLISH狀態的時候,雙方如何檢測連接的可用行。而http的keep-alive說的是如何避免進行重復的TCP三次握手和四次揮手的環節。


免責聲明!

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



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