什么是应用侧 TCP keepalive
TCP keepalive 让内核在连接空闲一段时间后主动发送探测报文,连续若干次没有回应就判定对端不可达并关闭连接,从而回收“对端已经消失但本端还认为是 established”的连接。它按 socket 生效:应用可以在单个连接上开启并定制空闲时间、探测间隔与失败次数,比改系统级 tcp_keepalive_* 参数更精确(系统参数只影响未单独设置的连接)。
基本信息
| 开启 | setsockopt(SOL_SOCKET, SO_KEEPALIVE, &one, ...) |
|---|---|
| 空闲时间 | TCP_KEEPIDLE(秒) |
| 探测间隔 | TCP_KEEPINTVL(秒) |
| 失败次数 | TCP_KEEPCNT |
| 系统级对应 | net.ipv4.tcp_keepalive_time / _intvl / _probes |
| 生效范围 | 仅对该 socket,且需连接处于空闲状态 |
典型使用场景
- 长连接服务回收僵尸连接:客户端异常断电或网络中断后及时释放资源
- 负载均衡后端:确认空闲连接不会长期占用会话表项
- 中间设备的超时策略差异:把探测时间设为小于设备空闲回收时间
- 与中间设备 NAT 表老化时间配合,避免连接被静默清除后应用仍在使用
- 连接池健康检查的补充手段
C 用例
C 用例
int one = 1, idle = 60, intvl = 10, cnt = 3;
/* 开启保活 */
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
/* 空闲 60 秒后开始探测 */
setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle));
/* 每 10 秒探测一次,连续 3 次无响应则断开 */
setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt));查看系统默认与连接状态
查看系统默认与连接状态
sysctl net.ipv4.tcp_keepalive_time net.ipv4.tcp_keepalive_intvl net.ipv4.tcp_keepalive_probes
ss -to state established | head -5 # timer 字段可看出 keepalive 计时
ss -tno | grep -m3 'timer:(keepalive'参数与行为
| 参数 | 含义 | 调整注意 |
|---|---|---|
| SO_KEEPALIVE | 是否开启保活 | 默认关闭,需显式开启 |
| TCP_KEEPIDLE | 空闲多久开始探测 | 应小于中间设备的空闲回收时间 |
| TCP_KEEPINTVL | 探测间隔 | 过密会增加无效流量 |
| TCP_KEEPCNT | 失败几次判定断开 | 结合业务超时容忍度设置 |
保活探测只对空闲连接起作用:有数据往来的连接不依赖它来检活,所以不能把它当成覆盖所有情况的健康检查手段。
系统级 tcp_keepalive_* 只影响未单独设置的连接,且修改后对新连接生效;用它替代应用层心跳,往往达不到业务要求的探活时效。