暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

基于bpftrace对PostgreSQL进行观测

原创 夏克 2023-03-17
1145

引子

前面几篇文章介绍了如何使用eBPF对数据库(PostgreSQL、OceanBase)进行观测,但给出的几个例子还是需要进行编码的,需要一些C/Python的基础,严格说还是需要“造轮子”的过程。因此对DBA来说并不是十分友好,这也有悖于我做这件事情的初衷。解决这个问题大概有两种思路,一是尽量开发一些通用的工具,二是寻求更简单的方法或工具,前者我试图筹划去写一套工具集(可能周期会比较长),而后者正是今天要介绍的一个更加工具——bpftrace。

摘要

eBPF有很多工具,按照封装程度由低到高分别是libbpf<bcc<bpftace,之前的例子使用BCC框架的python进行了演示,没有使用libbpf的原因是libbpf使用的开发语言是C(对比eBPF的原理学习比较适合使用libbpf),而这篇将采用封装度更高的bpftrace(类似于awk、Dtrace、SystemTap)来演示对PostgreSQL进行观测。

预备知识

eBPF是什么?eBPF能做什么?如何搭建eBPF环境?等等。这些内容不进行赘述了,可以参考下面几篇文章。

  1. PostgreSQL + eBPF实现数据库服务可观测
  2. OceanBase 4.0 改装:另一种全链路追踪的尝试
  3. 使用eBPF提升可观测性
  4. pg_lock_tracer实现数据库服务可观测
  5. eBPF实现“零”侵入的慢SQL抓取

什么是bpftrace

bpftrace是一个跟踪和排查Linux系统性能问题的工具,它基于eBPF技术,可以通过编写简单的脚本,实时监控内核的各种事件,如函数调用、系统调用、网络流量等。与传统的跟踪工具相比,bpftrace具有更低的性能开销和更高的灵活性,可以实时分析和优化系统性能,而无需停机或使用专门的硬件设备。同时,bpftrace提供了类似awk语法的脚本语言,使得用户可以轻松地编写和修改脚本,实现对特定问题的监控和分析。除此之外,bpftrace还支持用户自定义的探针和跟踪点,使得用户可以更加灵活地针对不同的应用场景进行监控和优化。总之,bpftrace是一个功能强大、易于使用的性能调试工具,对于Linux系统管理员和开发人员来说,是一个不可或缺的工具。

图片.png

安装bpftrace

Linux内核要求

建议使用Linux 4.9或更高版本的内核。一些工具可能适用于旧版本的内核,但是这些旧版本的内核已不再维护。以下是添加主要功能的内核版本:

  • 4.1 - kprobes
  • 4.3 - uprobes
  • 4.6 - stack traces, count and hist builtins (use PERCPU maps for accuracy and efficiency)
  • 4.7 - tracepoints
  • 4.9 - timers/profiling

内核还需要使用以下选项进行构建:

CONFIG_BPF=y CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT=y CONFIG_HAVE_EBPF_JIT=y CONFIG_BPF_EVENTS=y CONFIG_FTRACE_SYSCALLS=y CONFIG_FUNCTION_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_DYNAMIC_FTRACE=y CONFIG_HAVE_KPROBES=y CONFIG_KPROBES=y CONFIG_KPROBE_EVENTS=y CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_UPROBES=y CONFIG_UPROBE_EVENTS=y CONFIG_DEBUG_FS=y
  • 安装
sudo apt-get install -y bpftrace # ubuntu or sudo dnf install -y bpftrace #fedora

bpftrace学习路线

相对于BCC来说bpftrace的学习路线可能会相对陡峭,但学习周期比BCC要短的多,如果您有awk、Dtrace、SystemTap的基础,相信话3~5个小时就可以基本掌握bpftrace的使用方法,如果有一些C语言的底子可能这个周期会更短。

学习资料

个人推荐使用官方的文档。

  1. bpftrace Reference Guide(官方)
  2. bpftrace一行教程(官方<中文>)
  3. Linux性能工具-bpftrace入门

bpftrace支持探针类型

  • kprobe - kernel function start
  • kretprobe - kernel function return
  • uprobe - user-level function start
  • uretprobe - user-level function return
  • tracepoint - kernel static tracepoints
  • usdt - user-level static tracepoints
  • profile - timed sampling
  • interval - timed output
  • software - kernel software events
  • hardware - processor-level events

bpftrace内建变量

  • pid - Process ID (kernel tgid)
  • tid - Thread ID (kernel pid)
  • uid - User ID
  • gid - Group ID
  • nsecs - Nanosecond timestamp
  • elapsed - Nanoseconds since bpftrace initialization
  • numaid - NUMA Node ID
  • cpu - Processor ID
  • comm - Process name
  • kstack - Kernel stack trace
  • ustack - User stack trace
  • arg0, arg1, …, argN. - Arguments to the traced function; assumed to be 64 bits wide
  • sarg0, sarg1, …, sargN. - Arguments to the traced function (for programs that store arguments on the stack); assumed to be 64 bits wide
  • retval - Return value from traced function
  • func - Name of the traced function
  • probe - Full name of the probe
  • curtask - Current task struct as a u64
  • rand - Random number as a u32
  • cgroup - Cgroup ID of the current process
  • cpid - Child pid(u32), only valid with the -c command flag
  • $1, $2, …, $N, $#. - Positional parameters for the bpftrace program

案例演示

SQL抓取

用一行代码体验一下如何抓取SQL

sudo bpftrace -e 'usdt:/home/frank/pgsql/bin/postgres:postgresql:query__start { printf("SQL: %s\n",str(arg0));}'
  • 注解:参考官网

图片.png

  • 输出结果如下:

图片.png

抓取慢SQL

设计思路与上一篇eBPF实现“零”侵入的慢SQL抓取 一致。“PostgreSQL中的大部分探针(probe)都是成对出现的,这样我们可以方便的通过“开始”–“结束”探针被触发的时间差来计算各个阶段的耗时。这里我们用query__plan__startquery__plan__done 来观测SQL执行的总时长。”

#!/usr/bin/bpftrace BEGIN { printf("time(ms)\t sql\n"); @slow = 1 } usdt:/home/frank/pgsql/bin/postgres:postgresql:query__start { @start[arg0] = nsecs; } usdt:/home/frank/pgsql/bin/postgres:postgresql:query__done /@start[arg0]/ { @slow = $1; @usecs = ((nsecs - @start[arg0]) / 1000000); if(@usecs > @slow) { printf("%d(ms)\t %s\n", (@usecs), str(arg0)); } delete(@start[arg0]); } END { clear(@start); }
sudo bpftrace pg.bt 1

图片.png

只抓取了执行时间大于1ms的SQL,而select 1;并没有被抓取。

结论

这一系列帖子围绕eBPF对数据库可观测能力的提升进行了展开,从不同的维度,不同的工具做了简单的描述。可以根据您的知识背景选择一款适合您日常运维或排障的工具。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论