铜陵市网站建设_网站建设公司_过渡效果_seo优化
2025/12/24 9:39:42 网站建设 项目流程

前言

三年前第一次听说eBPF,觉得这玩意离我太远——内核开发?那是神仙干的事。

直到前段时间排查一个诡异的网络延迟问题,传统工具都定位不到根因,同事甩给我一个bpftrace脚本,几秒钟就抓到了问题。那一刻我才意识到,eBPF已经不是什么高深莫测的东西,而是实打实能解决问题的生产力工具。

这篇文章是我学习和使用eBPF的一些记录,不讲太多底层原理,主要聊聊怎么用它解决实际问题。

eBPF是什么

简单说,eBPF(extended Berkeley Packet Filter)让你可以在内核里安全地运行自定义程序,而不需要修改内核源码或加载内核模块。

传统的做法要观测内核行为,要么改内核重新编译,要么写个内核模块。两个方案都很重,风险也大。eBPF相当于在内核里开了个"沙盒",你的程序在里面跑,既能访问内核数据,又不会把系统搞崩。

能干什么

  • 网络:高性能负载均衡、DDoS防护、流量过滤
  • 安全:系统调用审计、入侵检测、容器安全
  • 观测:性能分析、延迟追踪、资源监控
  • 调试:内核函数追踪、用户态程序分析

Cloudflare用eBPF扛DDoS,Facebook用它做负载均衡,Cilium用它搞容器网络。这东西已经在生产环境大规模使用了。

环境准备

eBPF需要内核版本支持,最低4.x,建议5.x以上。Ubuntu 20.04/22.04都没问题。

# 检查内核版本uname-r# 5.15.0-91-generic# 安装BCC工具集(最常用的eBPF工具集)aptupdateaptinstall-y bpfcc-tools linux-headers-$(uname-r)# 安装bpftrace(高级追踪语言)aptinstall-y bpftrace# 验证安装bpftrace --version# bpftrace v0.14.0

实战一:追踪系统调用延迟

前几天遇到一个问题:某个Java服务响应变慢,但CPU、内存、IO看着都正常。

用bpftrace追踪一下read系统调用的延迟分布:

# 追踪read调用延迟(按进程名过滤)bpftrace -e' tracepoint:syscalls:sys_enter_read /comm == "java"/ { @start[tid] = nsecs; } tracepoint:syscalls:sys_exit_read /comm == "java" && @start[tid]/ { @usecs = hist((nsecs - @start[tid]) / 1000); delete(@start[tid]); } '

输出:

@usecs: [0] 156 |@@@@@@@@@@@@@@@ | [1] 489 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| [2, 4) 234 |@@@@@@@@@@@@@@@@@@@@@@@ | [4, 8) 67 |@@@@@@ | [8, 16) 23 |@@ | [16, 32) 12 |@ | [32, 64) 8 | | [64, 128) 3 | | [128, 256) 156 |@@@@@@@@@@@@@@@ | <-- 异常

128-256微秒这个区间的调用数量异常偏多,正常应该是单峰分布。进一步追踪发现是读取某个配置文件时,文件系统有锁竞争。

这种问题用传统工具(strace会拖慢进程太多)很难快速定位,eBPF几乎零开销。

实战二:网络延迟分析

生产环境有台机器TCP延迟偶发飙高,网络组说线路没问题。用tcpretrans追踪重传:

# BCC工具:追踪TCP重传/usr/share/bcc/tools/tcpretrans# 输出TIME PID IP LADDR:LPORT T>RADDR:RPORT STATE14:23:150410.0.1.5:443 R>10.0.2.8:52341 ESTABLISHED14:23:150410.0.1.5:443 R>10.0.2.8:52341 ESTABLISHED14:23:160410.0.1.5:443 R>10.0.2.8:52341 ESTABLISHED

同一个连接连续重传,问题缩小到10.0.2.x这个网段。最后查出来是那个机房的交换机有问题。

更进一步,看TCP连接延迟分布:

# 追踪TCP连接建立延迟/usr/share/bcc/tools/tcpconnlat# 输出PID COMM IP SADDR DADDR DPORT LAT(ms)1892curl410.0.1.510.0.2.8443245.121893curl410.0.1.510.0.2.8443312.451894curl410.0.1.510.0.3.94431.23

对比很明显,连10.0.2网段延迟高了两个数量级。

实战三:进程级资源监控

有个容器CPU用量一直很高,但top里看不出哪个函数在消耗。用profile工具:

# CPU采样火焰图数据/usr/share/bcc/tools/profile -p$(pgrep -f myapp)-f30>profile.out# 生成火焰图(需要安装FlameGraph)gitclone https://github.com/brendangregg/FlameGraph ./FlameGraph/flamegraph.pl profile.out>cpu.svg

火焰图一目了然,发现某个JSON解析函数占了40%的CPU。原来是每次请求都在重复解析同一个大配置文件,加个缓存解决。

实战四:自定义追踪点

有时候需要追踪特定的内核函数。比如想知道文件打开操作的分布:

bpftrace -e' kprobe:do_sys_openat2 { @files[str(arg1)] = count(); } interval:s:5 { print(@files); clear(@files); } '

输出每5秒打印一次文件打开统计:

@files[/etc/ld.so.cache]: 234 @files[/lib/x86_64-linux-gnu/libc.so.6]: 156 @files[/proc/self/status]: 89 @files[/app/config.json]: 67 ...

这种方式对排查"到底谁在频繁读写某个文件"特别有用。

写个简单的eBPF程序

BCC提供Python接口,写起来比较方便。追踪所有的execve调用(新进程启动):

#!/usr/bin/env python3frombccimportBPF# eBPF程序(C语言)prog=""" #include <linux/sched.h> struct data_t { u32 pid; char comm[TASK_COMM_LEN]; }; BPF_PERF_OUTPUT(events); int trace_execve(struct pt_regs *ctx) { struct data_t data = {}; data.pid = bpf_get_current_pid_tgid() >> 32; bpf_get_current_comm(&data.comm, sizeof(data.comm)); events.perf_submit(ctx, &data, sizeof(data)); return 0; } """b=BPF(text=prog)b.attach_kprobe(event="__x64_sys_execve",fn_name="trace_execve")print("追踪新进程启动,Ctrl+C退出...")defprint_event(cpu,data,size):event=b["events"].event(data)print(f"PID:{event.pid}, COMM:{event.comm.decode()}")b["events"].open_perf_buffer(print_event)whileTrue:b.perf_buffer_poll()

运行效果:

追踪新进程启动,Ctrl+C退出... PID: 12345, COMM: bash PID: 12346, COMM: ls PID: 12347, COMM: grep

这对安全审计很有价值——谁在服务器上执行了什么命令,一清二楚。

生产环境使用建议

性能开销

eBPF的开销很低,但不是零。几个原则:

  1. 过滤要前置:在eBPF程序里做过滤,而不是全量采集再在用户态过滤
  2. 采样而非全量:profile用采样,不要每个事件都追踪
  3. 控制输出频率:用interval聚合,不要每个事件都输出

常用工具速查

# 性能分析profile# CPU火焰图offcputime# Off-CPU时间分析runqlat# 运行队列延迟# 网络tcplife# TCP连接生命周期tcpretrans# TCP重传追踪tcpconnlat# TCP连接延迟# 磁盘IObiolatency# 块设备IO延迟biosnoop# 块设备IO追踪ext4slower# ext4慢操作# 内存memleak# 内存泄漏检测cachestat# 缓存命中率# 系统调用execsnoop# 进程启动追踪opensnoop# 文件打开追踪

多机器批量排查

遇到跨多台服务器的问题时,需要同时在多个节点运行eBPF工具做对比分析。这种场景下我会用星空组网先把各个网段的机器串起来,统一管理后再批量跑诊断脚本,比逐台SSH效率高很多。

进阶学习资源

  • 《BPF Performance Tools》by Brendan Gregg - 这本书是圣经级别的
  • bcc官方仓库:github.com/iovisor/bcc - 大量现成工具和示例
  • bpftrace参考:github.com/iovisor/bpftrace - 追踪语言文档
  • Cilium eBPF教程:docs.cilium.io - 网络方向的最佳实践

总结

eBPF不再是内核黑客的专属玩具。对于运维和后端开发来说,它是一个威力巨大的问题排查工具:

  1. 低开销:生产环境可用
  2. 高精度:内核级别的观测能力
  3. 灵活:可以自定义追踪逻辑
  4. 安全:内核保证程序不会搞崩系统

从BCC工具集入手,遇到问题先试试现成工具,熟练后再尝试写自定义追踪程序。这个学习路径比较平滑。

说实话,用惯了eBPF再回头看传统的排查手段,会觉得效率差太多。推荐每个做服务端的同学都了解一下。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询