$session_time 并非标准字段,需通过 ss -tni 的 age 字段估算连接存活时长;僵尸连接表现为 established 但长期无数据交换,应结合 age、retrans、rto 和 keepalive 状态识别。

$session_time 并不是 TCP 协议或 Linux 内核中标准定义的变量,也不是 netstat、ss 或 lsof 等工具直接输出的字段。在真实运维场景中,没有原生的 $session_time 字段可直接调用——它常被误用为对“连接存活时长”的模糊指代,实际需通过其他可观测指标间接推算。
要识别 TCP 集群中的僵尸连接(即已断开但未正确关闭的连接)和异常行为,关键不在于虚构一个 $session_time,而在于结合连接状态、时间戳、收发窗口与应用层心跳逻辑进行交叉判断。
什么是僵尸连接?
僵尸连接通常表现为:
- TCP 状态为
ESTABLISHED,但实际数据已停止交换数分钟甚至更久; - 对端已崩溃、网络中断或进程卡死,但本端未触发 FIN/RST,也未收到超时通知;
- 连接仍占用文件描述符、内存和端口资源,长期累积会导致连接耗尽、服务拒绝。
这类连接无法仅靠 ss -tn 或 netstat -an 的“当前状态”识别,必须引入时间维度分析。
如何估算连接存活时长并识别异常?
Linux 提供了若干可落地的时间线索,无需修改内核或依赖应用日志:
✅ 使用 ss 命令查看连接创建时间(推荐)
ss -tni | grep ESTAB
输出中含 age 字段(如 age: 12sec),表示该连接自建立以来的秒级存活时间。这是最接近“session time”的可靠指标。
- 若大量连接
age > 300(5分钟)且无新数据收发(rto、rttvar静止,retrans为 0),需警惕; - 若
age显示为0sec但状态是ESTAB,可能刚握手完成,也可能因内核版本差异未更新时间戳,需结合其他字段验证。
? 提示:
ss -tni中的i参数启用详细信息,包括重传计数(retrans)、RTT 估值(rtt)、RTO(rto)等,比netstat更实时、开销更低。
✅ 结合 lsof 查看 socket 创建时间戳(辅助验证)
lsof -iTCP -sTCP:ESTABLISHED -n -P | awk '{print $1,$2,$9}' | head -20
虽然 lsof 不直接显示连接起始时间,但可通过 /proc/[pid]/fd/ 下 socket 文件的 ctime(inode 更改时间)近似估算连接建立时刻(误差通常
ls -lc /proc/12345/fd/12 # 12 是某 TCP socket fd 编号
✅ 检查 TCP 层是否已静默超时(隐式僵尸信号)
观察以下字段组合:
-
retrans: 0+rto: 200ms+age: 600sec→ 长期无重传但连接未断:大概率对端失联,本端未检测到 FIN/RST; -
retrans: >3+rto持续翻倍 → 网络严重丢包或中间设备拦截,连接处于“半死”状态; -
timer:(keepalive,*)且timeo: 1200sec→ 正在走 keepalive 探测,若后续未收到 ACK,则会在约 20 分钟后由内核主动关闭(取决于net.ipv4.tcp_keepalive_time设置)。
⚠️ 注意:keepalive 默认关闭(除非应用显式开启
SO_KEEPALIVE),ZooKeeper、Redis 等中间件会自己实现应用层心跳,此时内核 keepalive 不生效,需单独监控其 session 超时逻辑(如 ZooKeeper 的sessionTimeout)。
如何批量识别异常连接?(Shell 快速脚本思路)
# 找出 age > 600 秒且无重传、接收窗口为 0 的 ESTABLISHED 连接(高危僵尸候选)
ss -tni state established | awk '
$1 ~ /^[0-9]+.[0-9]+.[0-9]+.[0-9]+:[0-9]+$/ &&
$NF ~ /age:/ && substr($NF,5)+0 > 600 &&
/rtt:/ && /retrans:0/ && /wscale:0|snd_wnd:0/ {print $0}
'
# 补充:统计各 IP 的长连接数量(排查单点异常客户端)
ss -tn state established | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -10
关键配置建议(预防优于诊断)
| 项目 | 推荐值 | 说明 |
|---|---|---|
net.ipv4.tcp_fin_timeout |
30 |
缩短 TIME_WAIT 状态持续时间,加快端口复用 |
net.ipv4.tcp_keepalive_time |
600(10 分钟) |
启用后,空闲连接 10 分钟开始发 keepalive 包 |
net.ipv4.tcp_keepalive_intvl |
75 |
每 75 秒发一次探测 |
net.ipv4.tcp_keepalive_probes |
9 |
连续 9 次无响应则关闭连接(约 11 分钟发现断连) |
| 应用层心跳间隔 | ≤ sessionTimeout / 3
|
如 ZooKeeper 设置 3000ms timeout,则客户端应每 ≤1000ms 发一次 ping |
? 补充:ZooKeeper 的
ConnectionLoss异常往往就源于 TCP 连接未及时感知断开,导致 session 在服务器端已过期,而客户端仍认为“在线”。
不复杂但容易忽略。











