0

0

服务器随机丢包但 ping 延迟正常的 perf + bpftrace 抓包定位

冰川箭仙

冰川箭仙

发布时间:2026-01-25 18:59:35

|

424人浏览过

|

来源于php中文网

原创

ping延迟正常但业务连接频繁超时或重传,因ping走独立ICMP路径,而TCP业务丢包可能发生在网卡驱动、软中断队列、GRO合并失败、XDP/tc策略等底层环节,需用eBPF和内核统计综合定位。

服务器随机丢包但 ping 延迟正常的 perf + bpftrace 抓包定位

为什么 ping 延迟正常但业务连接频繁超时或重传

因为 ping 只发 ICMP Echo Request,走的是内核独立的 ICMP 处理路径,不经过 TCP/IP 的连接管理、队列调度、拥塞控制等环节。真实业务(如 HTTP、gRPC)用的是 TCP,丢包可能发生在:网卡驱动收包中断丢失、软中断队列溢出、sk_buff 分配失败、socket 接收缓冲区满、甚至 eBPF 程序中误 drop。此时 ping 依然能通,但 tcpdump 在应用侧抓不到包,说明丢包发生在更底层。

perf record -e 'net:netif_receive_skb' 抓不到丢包点怎么办

这个 tracepoint 只在数据帧成功进入协议栈第一入口时触发,如果丢包发生在网卡 DMA 后但尚未调用 netif_receive_skb()(比如 NAPI poll 被延迟、RX ring 溢出、驱动丢包),它就完全沉默。必须上到更底层:

  • perf record -e 'skb:kfree_skb' 观察是否大量 skb 在极短时间内被释放,且 comm 字段为 ksoftirqd 或网卡驱动名(如 ixgbe),说明软中断处理不过来
  • 检查 /proc/net/snmpUdp: 行的 noportinerrors,或 Tcp: 行的 EstabResetsAttemptFails —— 这些是内核统计的真实丢包信号
  • 确认网卡是否启用了 LRO/GRO:ethtool -k eth0 | grep gro;GRO 合并失败时可能静默丢弃分片,且不记入常规计数器

bpftrace 跟踪 sk_buff 生命周期的关键位置

不能只盯 netif_receive_skb,要串联从 DMA 到 socket 的完整链路。以下 bpftrace one-liner 可快速定位异常释放点:

bpftrace -e '
kprobe:__kfree_skb {
  @kfree_reason[ksym(func)] = count();
}
kretprobe:dev_gro_receive /retval == NULL/ {
  @gro_fail[ustack] = count();
}
tracepoint:skb:kfree_skb /args->reason == 12/ {
  printf("DROPPED in %s (reason=12=SKB_DROP_REASON_PKT_TOO_SMALL)\n", ksym(args->func));
}'

注意:reason == 12 对应 SKB_DROP_REASON_PKT_TOO_SMALL,常见于 GRO 合并后校验失败;dev_gro_receive 返回 NULL 表示 GRO 流水线拒绝该包,往往因 IP ID 不连续或 TCP 选项不一致 —— 这类丢包不会进 tcpdump,但会显著影响长连接吞吐。

Mulan AI
Mulan AI

画布式AI视频创作平台,轻松制作爆款视频

下载

确认是否是 XDP 层或 tc ingress 丢包

如果服务器部署了 Cilium、Calico 或自定义 tc eBPF 策略,丢包可能发生在比 netif_receive_skb 更早的位置。检查:

  • tc filter show dev eth0 ingress —— 是否有 bpf 类型 filter 且 action 是 drop
  • ip link show eth0 查看是否有 xdp 标记;再运行 bpftool net show 确认 XDP 程序挂载状态
  • bpftrace -e 'kprobe:generic_xdp_tx { @xdp_drop = count(); }' 配合 xdp:xdp_exception tracepoint,判断是否触发了 XDP 异常路径

这类丢包完全绕过内核协议栈,netstat -s/proc/net/snmp 都不会体现,只能靠 eBPF 实时观测或驱动日志(dmesg | grep -i xdp)。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

234

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

437

2024.03.01

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

198

2023.11.20

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

394

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

574

2023.08.10

http500解决方法
http500解决方法

http500解决方法有检查服务器日志、检查代码错误、检查服务器配置、检查文件和目录权限、检查资源不足、更新软件版本、重启服务器或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

398

2023.11.09

http请求415错误怎么解决
http请求415错误怎么解决

解决方法:1、检查请求头中的Content-Type;2、检查请求体中的数据格式;3、使用适当的编码格式;4、使用适当的请求方法;5、检查服务器端的支持情况。更多http请求415错误怎么解决的相关内容,可以阅读下面的文章。

417

2023.11.14

HTTP 503错误解决方法
HTTP 503错误解决方法

HTTP 503错误表示服务器暂时无法处理请求。想了解更多http错误代码的相关内容,可以阅读本专题下面的文章。

2110

2024.03.12

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

45

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号