首页/系统/Linux 内核与性能调优速查/TCP_USER_TIMEOUT 控制未确认数据等待
网络栈调优98 条

TCP_USER_TIMEOUT 控制未确认数据等待

应用级超时接口: 设置后, 已发送数据在指定毫秒内未获确认即断开连接, 用于卡死连接的快速回收。

TCP_USER_TIMEOUT 是什么

TCP_USER_TIMEOUT 是 Linux 提供的套接字选项,单位毫秒。设置后,只要已经发出的数据在指定时间内没有收到确认,内核就认定连接不可用并主动断开,把对端假死、链路黑洞这类问题从「无期限等待」变成「确定时长后失败」。它与 SO_KEEPALIVE 的观测对象不同:keepalive 探测的是空闲连接,USER_TIMEOUT 管的是已有未确认数据的连接。

基本信息

适用平台Linux(setsockopt 选项,不是全局 sysctl 参数)
单位毫秒
典型调用setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &ms, sizeof(ms))
生效范围仅当前套接字,需要应用自己设置
与 keepalive 的分工keepalive 管空闲连接,USER_TIMEOUT 管未确认数据

典型使用场景

  • 长连接网关:对端进程卡死但 TCP 连接仍在时,避免请求线程被无限占住
  • 数据库驱动:连接池里的连接遇到网络中断后能及时失效,而不是长期挂起
  • 消息队列客户端:降低断网期间消息发送线程的阻塞时间
  • 跨机房调用:链路劣化时让请求快速失败,把重试交给上层
  • 代理与边车:在连接假死时及时释放文件描述符与内存

设置与观察

设置与观察
int ms = 30000;
setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &ms, sizeof(ms));   // 30 秒内未确认即断开
/* 观察:连接是否因超时被断开 */
/* ss -tin dst :3306 | grep -E 'retrans|timer' */

超时覆盖的故障

故障形态内核行为应用需要做什么
对端进程卡死不再读发送缓冲填满后无确认,超时后断开捕获连接错误并重建连接
链路黑洞持续丢包重传直至超过 USER_TIMEOUT快速失败并把重试交给上层
对端主机断电无 ACK,超时后释放连接清理连接池中的失效连接
tcp_keepalive_time 等内核参数只作用于空闲连接,不能替代 USER_TIMEOUT。连接上还有未确认数据时,keepalive 探测不会介入,这也是不少「连接假死」问题的根源。
取值要先测量链路的正常与抖动往返时间,再结合业务可容忍的最长等待来定;设得太短会在网络抖动时误断正常连接,反而制造故障。

易错点

  • 取值过短,在网络正常抖动时误断连接,表现为间歇性请求失败
  • 把它当成应用层重连与幂等设计的替代品,超时断连后数据一致性无人负责
  • 只在某一端设置,另一端仍会长期持有连接,问题只是被推到对侧
  • 在短连接为主的业务上花力气调它,收益远小于为长连接池配置合理的超时

数据来源与参考

  • man 7 tcp
  • Linux Documentation/networking/ip-sysctl.txt
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌