關於Keepalive的那些事

服務端不少同窗包括本身對keepalive理解不清晰,常常搞不清楚,TCP也有keepalive,HTTP也有keepalive,高可用也叫keepalive,常常混淆這幾個概念。作下這幾個概念的簡述,儘管名字基本上是同樣的,可是所表示意義和範疇卻截然不同。nginx

高可用 Keepalived

Keepalived是一個基於VRRP協議來實現的服務高可用方案,能夠利用其來避免IP單點故障。它的做用是檢測服務器的狀態,若是有一臺服務器宕機,或出現故障,Keepalived將檢測到,使用其餘服務器代替該服務器的工做,當服務器工做正常後Keepalived自動將服務器加入到服務器羣中。
Keepalived通常不會單獨出現,而是與其它負載均衡技術(如lvs、haproxy、nginx)一塊兒工做來達到集羣的高可用。web

一個簡單的使用例子,將域名解析到一臺負載均衡機器上,而後負載均衡反向代理到WEB機器上。中間的負載均衡只有一臺,無法作到高可用,至少須要作到兩臺,那配置成兩臺機器以後,Keepalived就能夠保證服務只有一個對外的虛擬IP,若是MASTER的負載均衡出現故障的時候,自動切換到BACKUP負載均衡上,服務不受任何影響。Keepalived來保證這些。服務器

咱們之前有過一套稍顯複雜的服務配置,Keepalived給HAProxy提供高可用,而後HAProxy給Twemproxy提供高可用和負載均衡,Twemproxy給Redis集羣提供高可用和負載均衡。提供負載均衡服務的基本都會保證高可用,咱們使用最多的Nginx做爲反向代理服務器的時候,就能保證web服務的高可用。網絡

nginx+keepalived 搭建高可用的服務教程有不少。感興趣的能夠本身試下搭建。負載均衡

TCP 的keepalive

TCP的keepalive主要目的是及時的釋放服務器資源。
經過TCP協議客戶端與服務器創建鏈接以後,若是客戶端一直不發送數據,或者隔很長時間才發送一次數據,當鏈接好久沒有數據傳輸時如何去肯定對方還在線,究竟是掉線了仍是確實沒有數據傳輸,鏈接是保持仍是關閉,多長時間或者在什麼樣的機制下鏈接應該關閉釋放資源。TCP的keepalive就是爲了解決這個問題才引入的。
TCP的keepalive主要是三個參數來控制tcp

tcp_keepalive_time 7200
心跳週期
tcp_keepalive_intvl 75
偵測包發送間隔
tcp_keepalive_probes 9
偵測包重試次數

解釋下這個流程和參數。
客戶端與服務器創建鏈接後,若是雙方在tcp_keepalive_time(7200S)後,沒有任何數據的傳輸,服務器就會每隔tcp_keepalive_intvl(75S)向客戶端發送探測包,判斷客戶端的鏈接狀態,大概包括客戶端崩潰、強制關閉了應用、主機不可達等的異常狀態。若是偵測包發送了tcp_keepalive_probes(9)次以後仍然沒有收到客戶端的回覆(就是ack包),服務器就會認爲這個鏈接已經不可用了,能夠丟棄或者關閉了。阿里雲

Nginx 的keepalive

TCP層已經有keepalive,爲何應用層的Nginx還須要keepalive?
我理解的是,使用TCP的keepalive的保證傳輸層鏈接的可用性,默認配置都是2小時的檢測週期。Nginx的keepalive來保證應用層的鏈接的可用性。一個在第四層傳輸層上保證可用性,一個在第七層應用層上保證應用層協議鏈接的可用性。
有本書裏面有提到:
爲何TCP keepalive不能替代應用層心跳?心跳除了說明應用程序還活着(進程還在,網絡通暢),更重要的是代表應用程序還能正常工做。而TCP keepalive由操做系統負責探查,即使進程死鎖或者阻塞,操做系統也會如常收發TCP keepalive信息,對方沒法得知這一異常。操作系統

nginx keepalive跟TCP的配置基本一致,只不過名字不同罷了。配置說明以下代理

so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]

so_keepalive=30m::10 表示開啓tcp偵測,30分鐘後無數據收發會發送偵測包,時間間隔使用系統默認的,發送10次偵測包。code

HTTP的keepalive

HTTP的keepalive比較常見,就是將短連接變成長連接。短鏈接是每一個請求響應,客戶端和服務器都要新建一個鏈接,完成以後當即斷開鏈接;當使用keepalive長鏈接時,客戶端到服務器端的創建鏈接,響應完成後鏈接不斷開,下次請求直接服用原來的鏈接,這樣就避免了重複創建鏈接和斷開鏈接的開銷。

那麼客戶端和服務器端是怎麼約定使用長鏈接通訊仍是短鏈接通訊。
主要Connection頭部

客戶端請求長鏈接頭部:Connection: keep-alive
服務端贊成使用長鏈接的響應頭部:Connection: keep-alive
二者缺一不可,若是服務器端不支持長鏈接:Connection: Close
若是是HTTP/1.1默認使用長鏈接,不管頭部是否是 Connection: keep-alive

注意的點:
Connection只對當前的鏈接雙方有效,而且Connection頭部不向後傳遞,只標識本身的鏈接狀態。
若是是多級代理又是什麼流程?
在這裏插入圖片描述
1客戶端與代理服務器1建連的時候帶了Connection: keep-alive,可是代理服務器1不支持長鏈接,回覆了Connection: Close,因此使二者用短鏈接
2代理服務器1與代理服務器2建連的時候使用Connection: Close短鏈接,代理服務器2回覆了Connection: Close,因此二者使用短鏈接
3代理服務器2與web機器建連的時候使用了Connection: keep-alive,web機器支持長鏈接,也回覆了Connection: keep-alive,因此二者使用長鏈接

HTTP的keepalive是開發者最長遇到的,因此要格外注意。不是服務器要求使用長鏈接鏈接就是長鏈接,是須要雙方都贊成才能使用長鏈接通訊。之前遇到過阿里雲的SLB就不支持長鏈接,WEB服務器或者代理服務器跟SLB鏈接的都是短鏈接。

相關文章
相關標籤/搜索