背景
項目中常常使用LVS作負載,當一個長鏈接的過段時間不發消息時,LVS以後就不會再轉發這個長鏈接的TCP數據包。後端
使用TCP長鏈接的場景
一種狀況:爲了節省TCP鏈接時間,咱們選擇創建幾個固定的TCP長鏈接,而後把全部的消息平均分配的這幾個TCP通道上傳送給對方。
另外一種狀況:客戶端和服務端之間是一個會話,要隔一段時間發個心跳。
bash
如今出現了第三種狀況,我是一個代理程序,要轉發一個會話,讓服務端和客戶端都無感知;並且多個會話能夠複用一個通路
(1)我須要在會話創建以前就創建鏈接;
(2)沒設計代理的心跳接口,我不能本身給後端發心跳;
但代理和後端之間隔着LVS。我不發心跳,LVS就偷偷地把長鏈接斷開了,而此時代理和後端都一無所知。從鏈接上看都是ESTABLISHED,一發消息就被RST。
tcp
這時咱們就用到了TCP自帶的keepalive機制。spa
配置TCP長鏈接參數
在Centos7上的嘗試,配置如下內核參數設計
# cat /etc/sysctl.conf net.ipv4.tcp_keepalive_time = 30 net.ipv4.tcp_keepalive_probes = 2 net.ipv4.tcp_keepalive_intvl = 20
可是沒見生效,在C++的程序中也開啓此機制:(也就是說得讓系統知道你是長鏈接)代理
int keepAlive = 5; int keepIdle = 5; int keepInterval = 5; int keepCount = 3; if(setsockopt(fd,SOL_SOCKET,SO_KEEPALIVE,(void*)&keepAlive,sizeof(keepAlive)) == -1) { printf("setsockopt SO_KEEPALIVE error!"); }
那發送間隔等參數的設置,最後以誰爲準呢?
答:/etc/sysctl.conf中配置的參數爲準。
code