time_wait是正常现象,量大说明客户端频繁主动关闭连接;默认持续60秒,占用socket元组;ss命令可精准统计,超5000需干预;启用tcp_tw_reuse最安全,但仅适用于本机作客户端场景;代码层应避免每请求新建并关闭socket,须用连接池或keep-alive复用连接。

TIME_WAIT 是正常现象,但量大说明客户端主动关闭连接太频繁
Linux 下每个 TIME_WAIT 状态连接会占用一个 socket 元组(源 IP+端口+目标 IP+端口),默认持续 2×MSL(通常 60 秒)。服务器上出现海量 TIME_WAIT,基本不是内核问题,而是业务逻辑中大量短连接被客户端(或本机作为客户端时)调用 close() 或析构导致的。尤其常见于:HTTP/1.0 短连、未复用 std::shared_ptr<:socket></:socket> 的 Boost.Asio 代码、或 C++ 客户端每请求新建 socket 并立即关闭。
用 ss -s 和 ss -tan state time-wait count 精准确认规模
别只看 netstat——它慢且在高并发下易卡死。ss 是更轻量、准确的替代:
ss -s | grep -i time ss -tan state time-wait | wc -l
如果输出 >5000,就值得干预;>20000 且持续不降,大概率是连接频发释放。注意区分方向:ss -tan state time-wait dst :80 看本机连外部 80 端口产生的 TIME_WAIT(即本机是客户端);而 ss -tan state time-wait src :8080 看外部连本机 8080 的残留(本机是服务端,此时 TIME_WAIT 实际在对方机器上)。
调整 net.ipv4.tcp_tw_reuse 是最安全的缓解手段
该参数允许内核重用处于 TIME_WAIT 状态的 socket 元组,**前提是对端开启了时间戳(TCP timestamps)**——现代 Linux/Windows 默认开启,所以一般可直接启用:
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse- 永久生效:在
/etc/sysctl.conf加一行net.ipv4.tcp_tw_reuse = 1,再运行sysctl -p - 它只影响「本机作为客户端发起连接」的场景(比如你的 C++ 服务调用其他 HTTP API),不影响服务端接收连接
- 不要开
tcp_tw_recycle(已从 Linux 4.12+ 移除),它在 NAT 环境下会导致连接失败
C++ 代码层必须避免每请求 new socket + close
这是根因,系统参数只是兜底。典型反模式:
// ❌ 错误:每次 HTTP 请求都新建 socket auto sock = std::make_unique<:socket>(ioc); sock->connect(ep); sock->write_some(buffer); sock.reset(); // → 触发 FIN,进入 TIME_WAIT</:socket>
正确做法取决于通信模式:
- HTTP 场景:用连接池(如
crow::client或自己维护std::deque<:shared_ptr>></:shared_ptr>),复用 socket 并发请求 - 自定义 TCP 协议:用
boost::asio::ip::tcp::iostream配合keep_alive选项,或手动设置socket.set_option(tcp::socket::keep_alive(true)) - 若必须短连,确保客户端(而非服务端)关闭连接——让 TIME_WAIT 落在对端机器上
真正棘手的是那些隐藏在第三方库内部的连接行为,比如某些 JSON-RPC 客户端默认禁用 keep-alive,得翻源码或抓包确认 FIN 发起方。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











