免费网站建设好不好,朗格手表网站,国内最好的wordpress主题,用ps做招生网站DBdoctor 是一款数据库内核级性能诊断工具#xff0c;利用eBPF技术深入数据库内核#xff0c;致力于解决数据库的一切性能问题。
被称之为“革命性”内核技术的eBPF一直以来都备受关注#xff0c;而DBdoctor作为一款数据库性能诊断工具#xff0c;首次将eBPF技术深入应用…DBdoctor 是一款数据库内核级性能诊断工具利用eBPF技术深入数据库内核致力于解决数据库的一切性能问题。
被称之为“革命性”内核技术的eBPF一直以来都备受关注而DBdoctor作为一款数据库性能诊断工具首次将eBPF技术深入应用在了数据库领域目前已涵盖SQL性能审核、问题SQL一分钟定位、锁分析、审计日志、根因诊断、索引推荐、智能巡检等诸多功能。很多小伙伴对如何利用eBPF技术观测数据库内核有浓厚兴趣因此我们在【DBdoctor】公众号开设了eBPF技术专栏将定期与您分享eBPF相关的技术文章手把手教您使用eBPF探测数据库欢迎关注我们
本文是eBPF专题的首篇将用一个具体的例子介绍如何采用eBPF在MySQL连接校验处加探针并打出hello world快来一起体验eBPF的强大吧 eBPF (extended Berkeley Packet Filter)是一种在Linux内核中执行代码的技术它允许开发人员在不修改内核代码的情况下运行特定的功能。传统的BPF 只能用于网络过滤而 eBPF则更加强大和灵活有更多的应用场景包括网络监控、安全过滤和性能分析等。uprobe是eBPF的一种使用方式它允许我们在用户空间的应用程序中插入代码来监控和分析内核中的函数调用。
具体来说eBPF uprobe可以在用户空间的应用程序中选择一个目标函数并在该函数执行之前和之后插入自定义的代码逻辑。这样可以实现对目标函数的监控、性能分析、错误检测等功能。通过eBPF uprobe我们可以在不修改内核源代码的情况下对内核中的函数进行动态追踪和分析。
工作原理 uprobe是一种用户探针uprobe探针允许在用户程序中动态插桩插桩位置包括函数入口、特定偏移处以及函数返回处。当我们定义uprobe时内核会在附加的指令上创建快速断点指令当程序执行到该指令时内核将触发事件程序陷入到内核态并以回调函数的方式调用探针函数执行完探针函数再返回到用户态继续执行后序的指令。
uprobe基于文件当一个二进制文件中的一个函数被跟踪时所有使用到这个文件的进程都会被插桩这样就可以在全系统范围内跟踪系统调用。uprobe适用于在用户态去解析一些内核态探针无法解析的流量例如http2流量报文header被编码内核无法解码、https流量加密流量内核无法解密等。 eBPF uprobe如何探测MySQL?
1环境准备 准备一台 Linux 机器安装好 Python 和内核开发包。注内核开发包版本必须和内核版本一致 安装带有符号表的MySQL 2基于BCC工具实现探测MySQL BCC程序使用 Python 编写它会嵌入一段 c 代码执行时将 c 代码编译成BPF字节码加载到内核运行。而 Python 代码可以通过 perf event 从内核将数据拷贝到用户空间读取到数据然后展示出来。
接下来我们将基于BCC的uprobe写一个eBPF程序观测MySQL上是否存在大量短连接。
a分析MySQL源码相关连接处理的函数 //从MySQL源码中分析函数选用了mysql-server层的连接校验处理函数check_connection
static int check_connection(THD *thd){...
}b导入BCC的BPF对象 #!/usr/bin/python
//这个对象可以将我们的观测代码嵌入到观测点中执行
from bcc import BPFc用c编写观测代码
bpf_text
#include uapi/linux/ptrace.h
#include linux/sched.h//定义结构体 data_t 保存我们每次观测到的结果
struct data_t {u32 pid;u32 tgid;u64 ts;char info[40];
};//PF_PERF_OUTPUT 定义了一个叫 events 的表观测代码可以将观测数据写入到 events 表中
BPF_PERF_OUTPUT(events);//该自定义函数用来和MySQL观察的内核函数进行绑定关联
int do_check_connection(struct pt_regs *ctx) {//获取了 MySQL 进程对应的结构体 task_struct然后从获取了其中的 线程pid 和 用户空间进程tgidstruct task_struct *t (struct task_struct *)bpf_get_current_task();//初始化data用来保存观测结果struct data_t data {};// create a new connectionchar a[] hello world,create a new connection;bpf_probe_read_kernel_str(data.info,sizeof(data.info),a);// process idbpf_probe_read(data.pid,sizeof(data.pid),t-pid);// thread idbpf_probe_read(data.tgid,sizeof(data.pid),t-tgid);// bpf_ktime_get_ns returns u64 number of nanoseconds. Starts at system boot time but stops during suspend.data.ts bpf_ktime_get_ns();//将观测的数据提交到表中events.perf_submit(ctx, data, sizeof(data));return 0;
}d观测代码关联MySQL 中需要观测的函数
# initialize BPF
//自定义的ebpf程序
b BPF(textbpf_text)
//将ebpf观察代码中的自定义函数和MySQL的内核函数进行绑定name为mysqld进程路径sym为编译后的探测函数名fn_name为绑定的ebpf自定义函数
b.attach_uprobe(name/home/mysqld, sym_ZL16check_connectionP3THD,fn_namedo_check_connection)e 打印观测结果
# output trace result.
print(Starting to Trace MySQL server do_check_connection function)
print(------------------------------------------------------------)//定义打印的回调函数
def print_event(cpu, data, size):event b[events].event(data)decoded_string event.info.decode(utf-8)print(%-35s, process id %-6s, thread id %-6s, sytem uptime(s) %-14s % (decoded_string,event.tgid, event.pid,event.ts/1000000000))//open_perf_buffer 将打印的回调函数注册到 events 表中
b[events].open_perf_buffer(print_event)
while 1:try:b.perf_buffer_poll()except KeyboardInterrupt:exit()f效果演示 执行该eBPF程序 分别开两个窗口执行连接MySQL的命令 打印观测的结果 从上面的演示中我们能看到客户端和MySQL建立连接的时候会打印日志显示这个连接的校验时间、线程id、进程id。如果存在大量日志输出说明数据库上一直在创建新连接即短连接再进行下一步分析是哪个应用程序导致的。 eBPF在程序开发过程中有哪些限制
eBPF在应用和开发过程中会出现多种问题下面就跟大家分享一下eBPF在程序开发过程中可能会遇到的限制
1栈大小512字节
eBPF单个探测函数对栈大小限制为512字节使用BPF_PERF_OUTPUT将数据从内核态输出到用户态时会直接限制单个数据结构的大小定义不能超过512字节。
2多参数获取
BCC中的宏定义从PT_REGS_PARM1(x)~PT_REGS_PARM5(x)栈传递的参数是从右边向左压栈想要获取探测函数的入参可以通过PT_REGS_PARM来获取但X86寄存器的个数是有限的BCC的定义是能取到5个参数对于超过6个参数的不能直接获取。
3循环遍历
Kernel 内核版本低于4.15不支持任何循环。
4复杂数据结构的解析
对于参数中复杂数据结构进行解析由于eBPF程序无法直接引用用户态的头文件且无法直接在eBPF代码中定义C的类对于复杂的数据结构获取其成员变量不能直接获取。
例
class THD: public MDL_context_owner,public Query_area,public Open_tables_state{public:MDL_context mdl_context;enum enum_mark_columns mark_used_columns;unlong wat_privilege;LEX *lex;bool gtid_executed_warning_issued;...private:...LEX_CSTRING m_catalog;}该数据结构较为复杂在使用eBPF获取该数据结构的m_catalog时显然是不能在内核中定义相同的数据结构来进行转换。
5uretprobe获取入参值
在uretprobe触发时寄存器中只能确保rax有效保留返回值无法直接获取函数入参的值。 利用eBPF技术探测MySQL ,具有更高效更扩展更安全等优势不用修改内核就可观测数据库性能。通过上面例子您是否发现采用eBPF跟踪数据库其实并不难主要的门槛在于精通数据库内核和Linux编程而且要对代码有精益求精的意识。您的hello world出现了吗欢迎进群跟我们探讨
专题二预告为什么eBPF可以重新定义数据库可观测 DBdoctor免费下载
1️⃣ 下载地址(安装包零依赖支持一键拉起耗时一分钟内)https://www.hisensecloud.com/h-col-126.html?statId9
2️⃣ 公众号DBdoctor
3️⃣ 在线试用
https://dbdoctor1.hisensecloud.com
关注公众号点击在线试用获取试用环境专属账号密码