前言

在日常运维工作中,当服务器出现性能问题时,传统方法(如 topvmstatstrace)往往只能提供有限信息,且会给系统带来额外开销。eBPF(extended Berkeley Packet Filter)作为一种内核级别的动态追踪技术,能够在几乎零开销的情况下,对运行中的内核和应用程序进行深度诊断,是现代运维工程师必备的利器。

本文将介绍如何利用 bpftrace 工具,快速定位生产环境中常见的 CPU 热点、内存泄漏和 I/O 延迟等性能瓶颈。

一、环境准备

1.1 检查内核支持

1
2
3
4
5
6
# 检查内核版本(需要 4.1+,推荐 5.x)
uname -r

# 检查 eBPF 是否启用
grep -E 'CONFIG_BPF|CONFIG_BPF_SYSCALL' /boot/config-$(uname -r)
# 应看到:CONFIG_BPF=y 和 CONFIG_BPF_SYSCALL=y

1.2 安装 bpftrace

1
2
3
4
5
6
7
8
# CentOS / RHEL
yum install -y bpftrace

# Ubuntu / Debian
apt install -y bpftrace

# 验证安装
bpftrace --version

注意:生产环境安装前建议先在测试机验证兼容性,部分精简版内核可能缺少必要的探针支持。

二、常见瓶颈场景与排查命令

2.1 CPU 热点定位

查看哪些函数占用了最多 CPU 时间:

1
2
3
4
5
# 每秒采样,统计各进程 CPU 占用(按 Ctrl+C 停止)
bpftrace -e 'profile:hz:99 { @[comm] = count(); }'

# 追踪用户态函数调用耗时(采样 30 秒)
bpftrace -e 'profile:hz:100 /pid == $1 / { @[ustack] = avg(lifetime); }' 1234

2.2 内存泄漏快速检测

1
2
3
4
5
6
7
# 每 5 秒打印内存分配/释放不平衡的进程
bpftrace -e 'struct alloc_args = { void* ptr; long len; }' \
'probe:__kmalloc /comm == "nginx"/ { @[comm] = sum(arg1); }
probe:__kfree /comm == "nginx"/ { @[comm] = sum(-arg0); }'

# 统计高頻内存分配点
bpftrace -e 'kmalloc { @[ksym(kaddr)] = count(); }' --interval 5s

2.3 I/O 延迟分析

1
2
3
4
5
# 追踪磁盘 I/O 延迟超过阈值的事件
bpftrace -e 'kprobe:blk_mq_start_request / arg1 > 10000 / {
@[comm, 1] = count();
@latency = hist((壁钟时间 - 起始时间) / 1000);
}'

2.4 网络连接异常追踪

1
2
3
4
5
6
7
8
9
10
# 追踪 TCP 重传事件
bpftrace -e 'tracepoint:tcp/tcp_retransmit_skb {
@[pid, comm] = count();
@dest[conn / 256] = count();
}'

# 监控高频 socket write 操作
bpftrace -e 'tracepoint:syscalls:sys_enter_write / fd > 2 / {
@[comm, fd] = hist(arg2);
}'

三、实战案例:Java 服务响应延迟突然升高

背景:某台运行 Tomcat 的服务器,GC 日志未见异常,但接口响应时间从 50ms 突增至 800ms。

排查步骤

  1. 初步采样:定位热点函数
1
bpftrace -e 'profile:hz:99 { @[ustack, comm] = count(); }' --interval 10s

输出显示大量时间消耗在 z矿泉水_read 系统调用上。

  1. 追踪文件操作:确定是哪个文件被频繁读取
1
2
3
bpftrace -e 'tracepoint:syscalls:sys_enter_read { 
printf("%d %s %s", pid, comm, comm);
}' | head -20

发现 Tomcat 进程反复读取同一个 30MB 的 Session 配置文件。

  1. 验证:对比文件修改时间
1
2
stat /data/tomcat-webapp/session-config.xml
# 发现文件在问题时间段被频繁更新

根因:应用层在做 Session 序列化时,每次请求都重新加载并解析了 30MB 的配置文件,而该文件在问题时段被运维脚本高频更新,导致大量 cache miss。

解决:在应用层增加文件内容缓存,避免每次请求都从磁盘读取。

四、使用注意事项

  1. 不要在生产环境盲目采样:部分采样命令(如 profile:hz:1000)在高负载机器上可能雪上加霜,建议先在测试环境评估开销。

  2. 采样时长控制:持续采样超过 1 分钟会产生大量数据,建议加 --interval 限制输出频率。

  3. 权限要求:bpftrace 需要 root 权限或 CAP_SYS_ADMIN 能力,确保操作安全可控。

  4. 结果解读:eBPF 只能告诉你”哪里慢了”,需要结合业务逻辑才能定位根因。

总结

eBPF 为运维工程师提供了一把锋利的瑞士军刀,相比传统的 strace、perf 工具,它具有更低开销、更强灵活性的优势。日常工作中,建议将 bpftrace 作为常规巡检工具的补充,当告警触发时快速上手定位,而不是等故障扩大再逐步排查。掌握好本文介绍的常用命令组合,可显著提升生产环境性能问题的定位效率。