必须先启用SO_KEEPALIVE选项,否则调小tcp_keepalive_time无效;该参数仅控制探测行为,前提是socket已通过setsockopt开启保活,未启用则完全不发探测包。

直接调小 tcp_keepalive_time 不够,必须同时确认应用层启用了 SO_KEEPALIVE,否则改了也白改。
为什么改了 tcp_keepalive_time 还是断连?
内核参数只控制“探测行为”,但前提是 socket 真的开启了保活。很多服务(如 Nginx、PostgreSQL、Go 默认 net.Conn)压根没调 setsockopt(..., SOL_SOCKET, SO_KEEPALIVE, ...),所以即使你把 tcp_keepalive_time 设成 30 秒,也不会发任何探测包。
- 验证是否启用:用
ss -ti查看某个活跃连接,输出里有keepalive字样才算真开了 - 常见静默失败场景:Alpine 镜像(musl libc)、旧版 Go runtime、某些 Java NIO 框架默认关闭
- 别只看
sysctl输出值——它只是“如果开了,就按这个规则来”,不是“自动帮你开”
怎么设 tcp_keepalive_time 才真正有效
目标不是越小越好,而是要小于链路中**最短的空闲超时阈值**,通常是防火墙或云厂商 NAT 网关的 300–600 秒。设大了发现不了断连,设太小(如 60 秒)可能被当成扫描流量丢弃,还增加无谓开销。
Linux AI 服务器 — 将 Linux 服务器转换为本地 AI 推理集群。使用 systemd、NVIDIA CUDA 实现无头 Linux AI,零 GUI 开销。
- 推荐值:
tcp_keepalive_time = 300(5 分钟),tcp_keepalive_intvl = 30(30 秒重试),tcp_keepalive_probes = 3(总探测窗口约 7.5 分钟) - 避免踩坑:
tcp_keepalive_probes = 1极易误杀(一次丢包就断),= 0表示禁用,别设成 1 - 注意兼容性:Linux 3.7+ 才支持 per-socket 的
TCP_KEEPIDLE等选项;老内核只能靠全局 sysctl
临时调 vs 永久生效:别漏掉加载步骤
用 sysctl -w 改完只是内存生效,重启就丢。生产环境必须落盘并显式加载,否则半夜重启后连接全断。
- 推荐写法:新建
/etc/sysctl.d/99-tcp-keepalive.conf,内容三行(等号前后留空格):net.ipv4.tcp_keepalive_time = 300net.ipv4.tcp_keepalive_intvl = 30net.ipv4.tcp_keepalive_probes = 3 - 加载命令必须用
sudo sysctl --system(比sysctl -p更健壮,会合并所有.d/下配置) - 验证是否真生效:
sysctl net.ipv4.tcp_keepalive_time输出应为 300,不是默认 7200
真正容易被忽略的是:TCP keepalive 只是“探测手段”,不是“保活开关”。它不发业务数据,无法绕过某些严格策略的中间设备;对高可靠场景,必须叠加应用层心跳(如 WebSocket ping/pong 或自定义 PING-PONG 协议)。


















