云优采集接口(本文的原理机制,如何使用火焰图快速定位性能问题)
优采云 发布时间: 2021-11-09 02:08云优采集接口(本文的原理机制,如何使用火焰图快速定位性能问题)
本文主要分享火焰图的使用,介绍了systemtap的原理和机制,如何使用火焰图快速定位性能问题的原因,同时加深对systemtap的理解。
让我们回想一下,作为编程新手,我们是如何调整程序的?当没有数据时,它通常基于主观假设。稍有经验的同学会二分不同的代码或者一块一块调试。这种定位问题的方法不仅费时费力,而且不具有普遍性。当遇到其他类似的性能问题时,需要反复踩坑填坑。如何避免这种情况?
俗话说:“工欲善其事,必先利其器”。我个人认为程序员也需要一个“利器”来定位性能问题。就像医生看病人一样,需要依靠专业的医疗工具(如X光、听诊器等)进行诊断,最终根据医生的检查结果快速准确地定位疾病的病因。工具。性能调优工具(如 perf / gprof 等)用于性能调优,就像 X 射线对患者一样。他们可以查明程序的性能瓶颈。
但是,常用的性能调优工具如perf只能在呈现内容中列出调用栈或者非分层的时间分布,不够直观。这里推荐大家一起使用火焰图,这样会更直观的呈现perf采集等工具的数据。
第一次认识火焰图
Flame Graph 是由 Linux 性能优化大师 Brendan Gregg 发明的。与所有其他分析方法不同,火焰图从全局角度查看时间分布。它从下到上列出了所有可能的原因。性能瓶颈的调用栈。
火焰图的整个图形看起来像一个跳动的火焰,这也是它名字的由来。
火焰图有以下特点(这里以on-cpu火焰图为例):
火焰图类型
常见的火焰图类型包括 On-CPU、Off-CPU、Memory、Hot/Cold、Differential 等。它们适合处理什么样的问题?
这里笔者主要使用了On-CPU、Off-CPU和Memory火焰图,所以这里仅对这三种火焰图进行比较,欢迎大家补充修正。
火焰图分析技巧 纵轴代表调用栈的深度(栈帧数),用于表示函数之间的调用关系:下面的函数是上面函数的父函数;横轴代表调用频率,格子宽度越大,说明越可能是瓶颈;不同类型的火焰图适用于不同的优化场景。比如on-cpu火焰图适合分析CPU占用率高的问题函数,off-cpu火焰图适合解决阻塞和锁抢占问题;无意义的东西:水平顺序是为了聚合,与函数之间的依赖或调用关系无关;火焰图的各种颜色是为了便于区分,没有特殊含义;更多实践:进行性能优化,有意识地使用火焰图进行性能调优(如果时间充裕);如何绘制火焰图?
要生成火焰图,必须有一个方便的动态跟踪工具。如果操作系统是 Linux,通常是 perf 或 systemtap 之一。其中,perf 是比较常用的。大多数Linux都收录perf,可以直接使用;SystemTap功能更强大,监控更灵活。关于如何使用perf绘制火焰图,网上有很多丰富的资料,所以本文以SystemTap为例。
SystemTap 是一个动态跟踪工具。它采用探测机制获取内核或应用的采集运行信息,让您无需修改内核和应用的代码即可获取丰富的信息,帮助您分析定位。解决问题。SystemTap 定义了类似的 DSL 脚本语言,方便用户根据需要自由扩展。但是,与动态跟踪的鼻祖 DTrace 不同,SystemTap 没有驻留在内核中的运行时。它需要将脚本编译成内核模块,然后插入内核执行。这也会导致 SystemTap 启动缓慢并依赖于完整的调试符号表。
使用SystemTap绘制火焰图的主要过程如下:
本文演示的步骤将基于操作系统Tlinux 2.2(Linux内核版本3.10.107)
安装 SystemTap 和操作系统符号调试表
使用 yum 工具安装 systemtap:
yum install systemtap systemtap-runtime
因为systemtap工具依赖完整的调试符号表,生产环境不同机器的内核版本不同(虽然都是Tlinux2.2个版本,但是内核版本后面的次要版本不同,可以使用uname -a命令查看)所以我们还需要安装kernel-debuginfo包和kernel-devel包。我这里已经安装了这两个依赖包。
kernel-devel-3.10.107-1-tlinux2-0046.x86_64
kernel-debuginfo-3.10.107-1-tlinux2-0046.x86_64
根据需要绘制的火焰图类型和流程类型选择合适的脚本
使用 SystemTap 进行统计,往往需要根据其语法编写脚本,具有一定的门槛。好在github上的spring兄(agentzh)开源了他常用的两套SystemTap脚本:openresty-systemtap-toolkit和stapxx。这两个工具集可以覆盖大部分C进程、nginx进程、Openresty进程的性能问题场景。.
这里需要绘制off-cpu火焰图,所以使用sample-bt-off-cpu脚本
生成内核模块
现在我们有了统计脚本并安装了systemtap,就可以正常使用了,但是因为systemtap通过生成内核模块来采集相关探针的统计信息,所以tlinux需要所有运行的内核模块先到达。tlinux平台签名可以运行,所以:
所以需要先修改off-cpu脚本生成内核模块;然后对内核模块进行签名;最后使用systemtap命令手动运行脚本统计监控数据。
Systemtap的执行过程如下:
所以这里我们修改off-cpu stap脚本,让它只运行到第四阶段,只生成一个内核模块
// 在 stap 命令后增加 -p4 参数,告诉systemtap,当前只需要执行到第四阶段
open my $in, "|stap -p4 --skip-badvars --all-modules -x $pid -d '$exec_path' --ldd $d_so_args $stap_args -"
or die "Cannot run stap: $!\n";
修改后运行脚本,会生成一个内核模块
// -p 8682 是需要监控的进程的进程号
// -t 30 是指会采样30秒
./sample-bt-off-cpu -p 8692 -t 30
生成的内核模块名称类似于 stap_xxxxx.ko 模块名称。由于读者不需要关心内核模块签名,因此跳过该章节
运行内核模块统计信息
内核模块签名后,可以使用staprun命令手动运行相关内核模块
命令:
// 注意:签名脚本会将生产的内核模块重命名,需要将名字改回去……(脚本bug)
staprun -x {进程号} {内核模块名} > demo.bt
值得注意的是,被监控的进程必须有一定的load systemtap才能采集获取相关数据,即在采集的时候,同时需要一定量的请求时间(一般是自己构造请求,强调过程))
将统计数据转换为火焰图
获取统计数据demo.bt后,可以使用火焰图工具绘制火焰图
下载火焰图,链接:
命令:
./stackcollapse-stap.pl demo.bt > demo.folded
./flamegraph.pl demo.folded > demo.svg
这样就得到了off-cpu火焰图:
看图说话
趁热打铁,通过几张火焰图熟悉如何使用火焰图
图片来自春哥微博或我最近画的表演火焰图
On-cpu 火焰图 Apache APISIX QPS 急剧下降
Apache APISIX 是一个开源的国产高性能 API 网关。在之前的选型和压测中发现,当Route与场景不匹配时,QPS急剧下降,其CPU(四十八核)占用率几乎达到100%。QPS只有几千。通过绘制火焰图发现,耗时主要在表插入阶段(lj_cf_table_insert)。分析代码发现该表没有发布。每次匹配不匹配时,都会将路由发送到一个表中进行统计。往表中插入一条数据导致表越来越大,后续插入时间过长导致QPS下降。
Off-cpu火焰图nginx互斥问题
这是一个 nginx 的 off-cpu 火焰图。我们可以快速锁定到 ngx_common_set_cache_fs_size -> ngx_shmtx_lock -> sem_wait。这个逻辑使用了互斥锁,它允许nginx进程将大部分等待时间花在获取锁上。
代理监控和报告断点问题
这是代理的 CPU 外火焰图。它是一个多线程异步事件模型。主线程处理每条消息,多个线程负责配置下发或监控上报。目前的问题是监控上报性能较差,无法在周期(一分钟)内完成监控数据上报,导致出现监控断点。通过off-cpu火焰图,我们可以分析报告线程花费大量时间使用curl_easy_perform接口发送和接收http监控数据消息。