tcp協議 中KeepAlive講解及tcp心跳維持方案

swoole中設置keepalive
在TCP中有一個Keep-Alive的機制可以檢測死連接,應用層如果對於死鏈接週期不敏感或者沒有實現心跳機制,可以使用操作系統提供的keepalive機制來踢掉死鏈接。 在Server::set配置中增加open_tcp_keepalive=>1表示啓用tcp keepalive。 另外,有3個選項可以對keepalive的細節進行調整。

Keep-Alive機制不會強制切斷連接,如果連接存在但是一直不發生數據交互。Keep-Alive不會切斷連接。而應用層實現的心跳檢測 heartbeat_check 即便連接存在,但不產生數據交互的情況下,依然會強制切斷連接。

TCP服務器心跳維持方案
正常情況下客戶端中斷TCP連接時,會發送一個FIN包,進行4次斷開握手來通知服務器。但一些異常情況下,如客戶端突然斷電斷網或者網絡異常,服務器可能無法得知客戶端已斷開連接。

尤其是移動網絡,TCP連接非常不穩定,所以需要一套機制來保證服務器和客戶端之間連接的有效性。

Swoole擴展本身內置了這種機制,開發者只需要配置一個參數即可啓用。Swoole在每次收到客戶端數據會記錄一個時間戳,當客戶端在一定時間內未向服務器端發送數據,那服務器會自動切斷連接。

使用方法:
$serv->set(array(
‘heartbeat_check_interval’ => 5,
‘heartbeat_idle_time’ => 10,
));
上面的設置就是每5秒偵測一次心跳,一個TCP連接如果在10秒內未向服務器端發送數據,將會被切斷。

在Linux內核設置KeepAlive

KeepAlive默認不是開啓的,如果想使用KeepAlive,需要在你的應用中設置SO_KEEPALIVE纔可以生效。

查看當前的配置:

cat /proc/sys/net/ipv4/tcp_keepalive_time

cat /proc/sys/net/ipv4/tcp_keepalive_intvl

cat /proc/sys/net/ipv4/tcp_keepalive_probes

在Linux中我們可以通過修改 /etc/sysctl.conf 的全局配置:

net.ipv4.tcp_keepalive_time=7200

net.ipv4.tcp_keepalive_intvl=75

net.ipv4.tcp_keepalive_probes=9

添加上面的配置後輸入 sysctl -p 使其生效,你可以使用 sysctl -a | grep keepalive 命令來查看當前的默認配置

如果應用中已經設置SO_KEEPALIVE,程序不用重啓,內核直接生效

KeepAlive

KeepAlive通過定時發送探測包來探測連接的對端是否存活, 但通常也會許多在業務層面處理的,他們之間的特點:

TCP自帶的KeepAlive使用簡單,發送的數據包相比應用層心跳檢測包更小,僅提供檢測連接功能

應用層心跳包不依賴於傳輸層協議,無論傳輸層協議是TCP還是UDP都可以用

應用層心跳包可以定製,可以應對更復雜的情況或傳輸一些額外信息

KeepAlive僅代表連接保持着,而心跳包往往還代表客戶端可正常工作

和Http中Keep-Alive的關係

HTTP協議的Keep-Alive意圖在於連接複用,同一個連接上串行方式傳遞請求-響應數據

TCP的KeepAlive機制意圖在於保活、心跳,檢測連接錯誤

TCP中已有SO_KEEPALIVE選項,爲什麼還要在應用層加入心跳包機制
因爲TCP協議中的SO_KEEPALIVE有幾個致命的缺陷:

keepalive只能檢測連接是否存活,不能檢測連接是否可用。比如服務器因爲負載過高導致無法響應請求但是連接仍然存在,此時keepalive無法判斷連接是否可用。
如果TCP連接中的另一方因爲停電突然斷網,我們並不知道連接斷開,此時發送數據失敗會進行重傳,由於重傳包的優先級要高於keepalive的數據包,因此keepalive的數據包無法發送出去。只有在長時間的重傳失敗之後我們才能判斷此連接斷開了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章