TCP Keepalivephp
Tcp keepalive的起源
雙方創建交互的鏈接,可是並非一直存在數據交互,有些鏈接會在數據交互完畢後,主動釋放鏈接,而有些不會,那麼在長時間無數據交互的時間段內,
交互雙方都有可能出現掉電、死機、異常重啓等各類意外,當這些意外發生以後,這些TCP鏈接並將來得及正常釋放,那麼,鏈接的另外一方並不知道對端的狀況,
它會一直維護這個鏈接,長時間的積累會致使很是多的半打開鏈接,形成端系統資源的消耗和浪費,爲了解決這個問題,在傳輸層能夠利用TCP的保活報文來實現。nginx
Tcp Keepalive存在的做用數據庫
1.探測鏈接的對端是否存活
在應用交互的過程當中,可能存在如下幾種狀況:
(1)客戶端或服務器意外斷電,死機,崩潰,重啓。
(2)中間網絡已經中斷,而客戶端與服務器並不知道。瀏覽器
利用保活探測功能,能夠探知這種對端的意外狀況,從而保證在乎外發生時,能夠釋放半打開的TCP鏈接。服務器
2.防止中間設備因超時刪除鏈接相關的鏈接表
中間設備如防火牆等,會爲通過它的數據報文創建相關的鏈接信息表,併爲其設置一個超時時間的定時器,若是超出預約時間,某鏈接無任何報文交互的話,
中間設備會將該鏈接信息從表中刪除,在刪除後,再有應用報文過來時,中間設備將丟棄該報文,從而致使應用出現異常,這個交互的過程大體以下圖所示:網絡
這種狀況在有防火牆的應用環境下很是常見,這會給某些長時間無數據交互可是又要長時間維持鏈接的應用(如數據庫)帶來很大的影響,爲了解決這個問題,
應用自己或TCP能夠經過保活報文來維持中間設備中該鏈接的信息,(也能夠在中間設備上開啓長鏈接屬性或調高鏈接表的釋放時間來解決,
可是,這個影響可能較大,有機會再針對這個作詳細的描述,在此很少說)。socket
常見應用故障場景:tcp
某財務應用,在客戶端須要填寫大量的表單數據,在客戶端與服務器端創建TCP鏈接後,客戶端終端使用者將花費幾分鐘甚至幾十分鐘填寫表單相關信息,
終端使用者終於填好表單所需信息後,點擊「提交」按鈕,結果,這個時候因爲中間設備早已經將這個TCP鏈接從鏈接表中刪除了,
其將直接丟棄這個報文或者給客戶端發送RST報文,應用故障產生,這將致使客戶端終端使用者全部的工做將須要從新來過,給使用者帶來極大的不便和損失。 性能
TCP保活報文交互過程 spa
TCP保活可能帶來的問題
1.中間設備因大量保活鏈接,致使其鏈接表滿
網關設備因爲保活問題,致使其鏈接表滿,沒法新建鏈接(XX局網閘故障案例)或性能降低嚴重
2.正常鏈接被釋放
當鏈接一端在發送保活探測報文時,中間網絡正好因爲各類異常(如鏈路中斷、中間設備重啓等)而沒法將該保活探測報文正確轉發至對端時,
可能會致使探測的一方釋放原本正常的鏈接,可是這種可能狀況發生的機率較小,另外,通常也能夠增長保活探測報文發生的次數來減少這種狀況發生的機率和影響。
HTTP Keepalive
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鏈接。
1.在沒有設置 keepalive_timeout狀況下,一個socket資源從創建到真正釋放須要通過的時間是:創建tcp鏈接 + 傳送http請求 + php腳本執行 + 傳送http響應 + 關閉tcp鏈接
2.設置了keepalive_timout時間狀況下,一個socket創建到釋放須要的時間是多了keepalive_timeout時間。
http keep-alive與tcp keep-alive
http keep-alive與tcp keep-alive,不是同一回事,意圖不同。http keep-alive是爲了讓tcp活得更久一點,以便在同一個鏈接上傳送多個http,
提升socket的效率。而tcp keep-alive是TCP的一種檢測TCP鏈接情況的保鮮機制。tcp keep-alive保鮮定時器,支持三個系統內核配置參數:
echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 15 > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo 5 > /proc/sys/net/ipv4/tcp_keepalive_probes
keepalive是TCP保鮮定時器,當網絡兩端創建了TCP鏈接以後,閒置idle(雙方沒有任何數據流發送往來)了 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分鐘足夠了。也就是說,僅當nginx的keepalive_timeout值設置高於tcp_keepalive_time,
而且距此tcp鏈接傳輸的最後一個http響應,通過了tcp_keepalive_time時間以後,操做系統纔會發送偵測包來決定是否要丟棄這個TCP鏈接。
通常不會出現這種狀況, 除非你須要這樣作。
keep-alive與TIME_WAIT 使用http keep-alvie,能夠減小服務端TIME_WAIT數量(由於由服務端httpd守護進程主動關閉鏈接)。道理很簡單,相較而言,啓用keep-alive, 創建的tcp鏈接更少了,天然要被關閉的tcp鏈接也相應更少了。