ss -tni 的 timer 字段仅表示内核定时器(如 keepalive 或重传)剩余时间,非连接建立耗时;测 tcp 建连应使用 curl -w %{time_connect}、time + nc 或 socket 程序精确计时,并排查服务端队列积压与内核参数。

ss -tni 的 timer 字段不是连接建立耗时
执行 ss -tni 看到类似 timer:(on,15sec,0) 的输出,容易误以为是“这个连接已存在 15 秒”,其实它只表示某个内核定时器(比如 keepalive 或 retransmit)处于激活状态、剩余约 15 秒,并不反映连接从 SYN_SENT 到 ESTABLISHED 的真实建立耗时。内核根本不向用户空间暴露连接建立的精确时间戳,ss 也没有对应字段。
用 curl -w 测 HTTP 连接各阶段耗时(含 TCP 建连)
如果你实际想测的是「HTTP 请求中 TCP 连接建立花了多久」,curl -w 是最直接可用的方案:
-
-o /dev/null -s必须加,否则响应体或进度条会污染输出 -
%{time_connect}表示从请求发起 → TCP 连接成功(三次握手完成),单位秒,精度纳秒级 -
%{time_namelookup}是 DNS 耗时,%{time_connect} - %{time_namelookup}才是纯 TCP 建连时间 - HTTPS 下可叠加
%{time_appconnect}观察 TLS 握手是否拖慢建连
示例命令:curl -o /dev/null -s -w "DNS:%{time_namelookup}\nTCP:%{time_connect}\n" https://example.com
测裸 TCP 连接建立耗时:用 time + nc 或自写 socket 程序
对非 HTTP 场景(如 Redis、MySQL 直连),curl 不适用,需绕过应用层:
-
time nc -zv host port可粗略测单次建连,但time统计含进程启动开销,误差常达 10–50ms - 更准的做法是写一个最小 socket 程序(C/Python),调用
connect()前后用clock_gettime(CLOCK_MONOTONIC, ...)计时 - 批量测量时,避免复用连接:每次新建 socket,禁用
SO_REUSEADDR,防止 TIME-WAIT 干扰
Python 示例片段:
import socket, time<br>s = socket.socket()<br>start = time.monotonic()<br>s.connect(('example.com', 443))<br>print(f"connect took {(time.monotonic() - start)*1000:.2f} ms")
生产环境排查:看 %sy 和 ss -lnt 是否有队列积压
如果大量连接建连慢,往往不是单次耗时高,而是服务端资源瓶颈:
- 运行
top观察%sy是否持续 >30%,说明内核协议栈处理压力大 -
ss -lnt查看监听端口的Recv-Q(全连接队列)和Send-Q(半连接队列),非零且持续增长即表明队列溢出 - 确认内核参数:
net.core.somaxconn(全队列上限)、net.ipv4.tcp_max_syn_backlog(半队列上限)是否足够
真正耗时的从来不是单次 connect 系统调用本身,而是它在内核里排队等待被 accept 的那几百毫秒——这点最容易被忽略。











