🚀 2025 年中国信息通信研究院《OSCAR 尖峰开源项目及开源社区》、腾讯科技《杰出贡献奖》、CNCF Landscape。欢迎 GitHub ❤️

博客

TCP 重传?用 tcpshark 追踪连接与内核丢包

概要

接口超时,TCP 重传计数上涨:究竟是哪条连接、哪个容器出了问题?仅凭节点级指标,很难确定下一步该查哪里。HUATUO tcpshark 捕获内核重传事件,定位连接、阶段和容器,并自动结合 dropwatch 查找本机丢包证据。本文通过实际命令和案例,介绍如何从重传告警逐步缩小故障范围。

为什么需要 tcpshark

工具 能回答的问题 主要局限
nstatnetstat -s 节点重传计数是否增长 无法定位连接、方向和容器
ss -ti 当前 socket 的 RTT、拥塞和重传快照 难以捕获短连接,不提供逐次事件
BCC tcpretrans 哪条流发生了重传或 TLP 缺少 tcpshark 提供的阶段分类、容器解析和丢包关联
tcpdump、Wireshark 报文时序、ACK/SACK 和疑似重传 需要选择抓包点并保存、重组流量,繁忙节点上开销较高

tcpshark 观测以下内核路径:

  • tcp/tcp_retransmit_skb:观测常规重传队列中的 SKB 重传;
  • tcp/tcp_retransmit_synack:观测服务端建连时的 SYN-ACK 重传;
  • tcp_send_loss_probe:观测 Tail Loss Probe。

输出的事件包含四元组、TCP 状态、序列号、拥塞控制状态、重传计数器和 socket 元数据,并在用户态生成 phasetcp_reason。这些信息支撑三层下钻:

  1. 从主机网络命名空间下钻到容器节点。
  2. 从容器节点下钻到具体连接和方向。
  3. 从连接下钻到建连、数据传输或关闭阶段等阶段;

如何使用 tcpshark

tcpshark 指定 --mode retransmittcp_retransmit.o 的实际路径。以下命令采集 60 秒,以 10.0.0.1:443-444 过滤常规重传,同时启用 TLP,并以 NDJSON 格式输出:

1
2
3
4
5
6
sudo ./tcpshark --mode retransmit \
  --enable-tlp \
  --bpf-path bpf/tcp_retransmit.o \
  --filter "tcp and host 10.0.0.1 and portrange 443-444" \
  --duration 60 \
  --output json

观察目标连接的 TCP 重传和 TLP 事件

以下参数直接影响采集范围和结果完整性:

  • --duration 60 将采集限制在业务异常窗口内;设为 0 时持续运行,直至收到退出信号;
  • --enable-tlp 默认关闭,启用后额外挂载 tcp_send_loss_probe 并输出 TLP 事件;
  • --filter 使用 tcpdump 风格表达式;
  • --max-events-per-second 100 在 BPF 侧限制事件速率。

独立运行 tcpshark 时,不会包含 container_id。通过 huatuo-bamai 运行时,系统会依次根据 socket 的内存 cgroup、网络命名空间 cookie 和 inum 解析容器归属。下图中的重传连接来自容器 tcpshark-container-demo

TCP 重传事件的容器归属

TCP 重传事件的容器归属

如何分析故障

不能仅凭 tcp_reason="RTO" 判断网络丢包。建议依次确认连接、阶段、重传路径、关联容器以及丢包位置等。

第一步:确认连接

以第一张图的第一条事件为例:

  1. 10.0.0.2:33342 > 10.0.0.1:443tcp_saddrtcp_sporttcp_daddrtcp_dport 共同标识连接与方向;
  2. phase="connect"tcp_state="SYN_SENT"tcp_flags="SYN"表明正在建立连接;
  3. tcp_reason="RTO",前两条事件的 icsk_retransmits 依次为 12,且 tcp_seq 相同:同一个 SYN 连续重试,直接影响建连延迟;
  4. net_namespace_inum=4026532512:事件来自该网络命名空间。

第二步:判断连接阶段和路径

phase 将重传分为 connectdataclosetcp_reason 根据事件类型、sk_stateca_state 和乱序计数器进一步分类。

观测信号 直接含义 优先检查
connect/RTOSYN 主动端发起 SYN 重传 路由、ACL/防火墙、负载均衡、对端监听和 SYN 队列
tcp_retransmit_synack 服务端发起 SYN-ACK 重传 回程链路、客户端状态、防火墙和握手队列
data/RTO 已建立连接进入 Loss 状态或命中 RTO 回退分类 主机丢包、网卡、链路拥塞、对端处理和 ACK 返回路径
data/fast_retransmit 探针触发时 socket 处于 Recovery 状态 丢包、乱序、ECMP 路径差异及 SACK/RACK 行为
TLP 内核正在执行尾部丢包探测 结合后续 ACK、RTO 和业务延迟判断,不能直接认定已经丢包
close/RTO 关闭阶段报文没有按期确认 对端退出、连接回收、FIN 路径和中间设备超时策略

使用分类结果时需结合上下文:

  • RTO 通常对延迟影响较大。优先关注持续出现、相同序列号反复出现或与业务毛刺对齐的事件;
  • fast_retransmit 表示 socket 处于 Recovery 状态,不代表 tcpshark 已还原完整的重复 ACK、SACK 或 RACK 决策过程;
  • unknown 表示当前快照不足以分类,不能作为无效事件丢弃。

如需只查看 RTO,可过滤 JSON 输出:

1
2
3
4
5
6
7
sudo ./tcpshark --mode retransmit \
  --enable-tlp \
  --bpf-path bpf/tcp_retransmit.o \
  --filter "tcp and host 10.0.0.1 and portrange 443-444" \
  --duration 60 \
  --output json |
  jq --unbuffered -cC 'select(.tcp_reason == "RTO")'

只查看 RTO 重传事件

第三步:判断是否持续

出现以下信号时,应提高排查优先级:

  • icsk_retransmits 持续增长;
  • 多条连接集中访问同一目的地址、端口或工作负载;
  • RTO 与应用延迟、超时或吞吐下降出现在同一时间窗。

对保存的 NDJSON 按目标、阶段和分类聚合,可快速识别主要异常方向:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
./_output/bin/tcpshark \
  --mode retransmit \
  --enable-tlp \
  --bpf-path ./_output/bpf/tcp_retransmit.o \
  --filter 'tcp and portrange 19991-19998' \
  --duration 90 \
  --output json |
  tee tcpshark.ndjson |
  jq -r \
    '[.phase, .tcp_reason, .event_type] | @tsv' |
  sort |
  uniq -c |
  sort -nr

TCP 重传分类聚合

第四步:开启丢包检测

指定 --with-dropwatch 后,tcpshark 会加载本机丢包检测功能并自动关联,当前丢包是否由于丢包引起。

1
2
3
4
5
6
./_output/bin/tcpshark \
  --mode retransmit \
  --with-dropwatch \
  --bpf-path-dir ./_output/bpf \
  --filter 'tcp and port 19997' \
  --output json | jq --unbuffered -cC 'select(.drop_location == "host_software")'
TCP 重传与 dropwatch 关联结果及本机软件丢包调用栈

接入 huatuo

除命令行临时采集外,还可通过 huatuo-bamai 持续观测物理机和容器中的 TCP 重传。在 huatuo-bamai 中配置过滤条件、TLP 采集和事件限速:

1
2
3
4
5
[EventTracing.TCPRetransmit]
Filter = "tcp and port 443"
EnableTLP = true
MaxEventsPerSecond = 100
EnableDropwatchCorrelation = true

tcp_retransmit tracer 默认位于全局 BlackList。启用前需将其移出并重启 huatuo-bamai。关联分析使用 tcpshark 内置的 dropwatch source,独立的 dropwatch 可继续保留在 BlackList 中;仅在需要单独保存原始丢包事件时启用。

详细参数、字段和分类规则见 tcpshark 使用文档

项目地址:github.com/ccfos/huatuo