
你是不是也遇到过这种情况:
系统没报错,CPU 正常,内存正常,服务日志也看不出什么花样,甚至网络 ping 过去毫秒级没问题……但就是,有用户在跟你说:
“为啥我们系统偶尔卡一下、消息延迟、偶尔上传失败?”
你查了一圈,也只是耸耸肩:“看上去挺正常啊。”
是啊,表面一切正常。但真正的问题,往往藏在 TCP 协议的深处。你以为是“偶发抖动”?其实是——TCP 重传。
重传这件事,表面上“没啥”,实际上“要命”
TCP 是可靠协议,它不会轻易让你丢包。它会悄悄地,在你不知道的情况下,“重传”丢失的数据包。重传机制能掩盖问题,但也让问题变得更难被发现。
你以为一次请求慢一点是“正常波动”,其实是某条链路发生了轻微但频繁的丢包,TCP 花了几次才把包送到。
这就是网络抖动最隐蔽、最难捉摸的一种形态。你不监控 TCP 重传,你根本就不知道用户是否在“水下挣扎”。
日志、抓包、ping 测不了 TCP 抖动
很多人第一反应是去抓包(tcpdump)、跑 ping、看 ELK 日志。但问题是:
- ping 只能看 ICMP 层,不能反映实际 TCP 应用流的状态
- 抓包成本太高,不能长期部署
- 日志?大多数服务根本不会记录 TCP 层级别的异常
所以你需要的,是一个更深入、更底层、更实时的监控方式。
eBPF:内核级“显微镜”,抓住每一次 TCP 重传
eBPF(Extended Berkeley Packet Filter)是 Linux 内核中一项强大技术。它能让你把程序“挂”在系统调用、协议栈、内核事件的关键点上,实现“非侵入式”监控。
用 eBPF,你可以做到:
- 不修改业务代码
- 不影响系统性能
- 实时统计 TCP 重传事件
- 精确到 PID、IP、端口、协议
哪些 TCP 重传指标值得关注?
我们关心的不是“是否重传”,而是“多少次”、“多频繁”、“多严重”。
你可以重点观测:
指标 | 说明 |
---|---|
tcp_retransmit_skb | TCP 层触发重传的系统调用事件 |
tcp_retransmits | 某连接累计重传次数 |
retransmit_rate | 某时间窗口内重传占比 |
reset_count | 被动关闭连接(Rst)次数(可能因重传失败) |
eBPF 工具推荐:bcc + tcptracer
你不需要自己写 BPF 程序,社区已经有成熟工具了,比如:
bashsudo /usr/share/bcc/tools/tcpretrans
输出类似于:
nginxTIME PID LADDR:PORT RADDR:PORT RETRANS
08:32:10 2167 10.0.0.12:42354 → 10.0.0.34:443 2
你会看到:
- 哪个进程
- 连到哪个 IP、哪个端口
- 在什么时候重传了多少次
这就叫“透明式审讯”,比翻日志准得多。
Prometheus + eBPF 指标接入
借助 cilium/ebpf 或 gobpf, 你可以将捕捉到的 TCP 重传信息封装成 Prometheus 指标。
例如:
prometheustcp_retransmits_total{src_ip="10.0.0.1", dst_ip="10.0.0.2", dst_port="443", pid="1234"}
再配上 rate(...)
的时间窗口,就能做出“重传率”的趋势图。
告警策略怎么设?
你不能只要一重传就报警,那会疯。你要的是:连续异常 + 某端口/服务聚集性异常 + 重传比超过某阈值。
yamlgroups:
- name: tcp-retrans
rules:
- alert: TCPRetransSpike
expr: rate(tcp_retransmits_total[30s]) > 5
for: 1m
labels:
severity: warning
annotations:
summary: "TCP 重传率异常升高"
description: "目标端口 443 出现频繁 TCP 重传,可能为网络抖动或链路异常"
你也可以写复合条件告警:
yamlexpr: (rate(tcp_retransmits_total[1m]) > 10)
and (rate(tcp_resets_total[1m]) > 3)
说明重传后连接被重置,更像是“链路损坏”而非单纯抖动。
Grafana 面板怎么做?
建议展示:
- TCP 重传次数趋势图(按服务、端口)
- 重传连接热力图(按 IP 分布)
- 重传 vs 正常连接比例图
- TCP reset、丢包比趋势
TCP 重传出现在哪些业务场景最多?
- 公网链路:客户端在外网,移动设备信号弱,易抖动
- 多租户云服务:VPC 内共享网络资源,可能瞬时爆负
- 跨 AZ / 跨区域通信:链路路径复杂,容易丢包
- 大型文件上传/下载服务:单连接承载数据量大,传输时间长,抖动更敏感
重传问题不止“慢”,还会“炸”
你以为最多就是“慢一点”,其实会有这些副作用:
- 连接长时间占用 → file descriptor 数爆满
- 服务堆积数据未处理 → 消息阻塞/超时
- client 重试 + TCP 重传双重压力 → 更容易雪崩
- 最终用户体验极差 → 转化流失、口碑受损
特别是 WebSocket、MQ、GRPC 这种“长连接高频通讯”的服务,对 TCP 抖动极其敏感。
延伸用途:SLO + 根因追踪
除了告警,你还可以:
- 把重传率作为服务质量 SLI/SLO 指标
- 结合 tracing 系统(如 Jaeger)→ 报错链路回溯时标记“TCP 抖动”
- 在网络拓扑图中标出“重传热点”
这会让你从“知道哪里炸了”到“知道为啥炸”。
eBPF 把你变成“内核特工”,让你能看得比别人更深
传统监控只能看得见症状,eBPF 让你看到“神经反应”。TCP 重传不是 bug,但它是信号,是警告,是你提前看见雪崩的雷达。
别再等用户喊“卡顿”才着急翻日志了。你可以:
- 持续采集 TCP 重传指标
- 配置智能告警策略
- 快速定位到具体服务、IP、连接
- 结合 Grafana 全景呈现
- 用数据做反向压力测试分析
你盯住的不是“服务有没有报错”,而是“网络有没有轻微抽搐”。这就是现代运维的底线感知力。
如果你还没有把 eBPF 用到你线上系统中,下一次用户说“这个页面又卡了”,你还是只能说那句最无力的话:
“我这边看起来一切正常。”