网页游戏源码怎么获取,充电宝seo关键词优化,做网站需要哪些工程师,wordpress上传文件去重复1. 介绍
eBPF#xff08;extened Berkeley Packet Filter#xff09;是一种内核技术#xff0c;它允许开发人员在不修改内核代码的情况下运行特定的功能。eBPF 的概念源自于 Berkeley Packet Filter#xff08;BPF#xff09;#xff0c;后者是由贝尔实验室开发的一种网…1. 介绍
eBPFextened Berkeley Packet Filter是一种内核技术它允许开发人员在不修改内核代码的情况下运行特定的功能。eBPF 的概念源自于 Berkeley Packet FilterBPF后者是由贝尔实验室开发的一种网络过滤器可以捕获和过滤网络数据包。 eBPF 可以在不侵入任何业务代码的基础上实现应用的可观测性。但是 eBPF 对 Linux 内核版本是有一定要求的4.14 以上。
2. 工作原理
eBPF 的工作原理主要分为三个步骤加载、编译和执行。
eBPF 需要在内核中运行。这通常是由用户态的应用程序完成的它会通过系统调用来加载 eBPF 程序。在加载过程中内核会将 eBPF 程序的代码复制到内核空间。
eBPF 程序需要经过编译和执行。这通常是由Clang/LLVM的编译器完成然后形成字节码后将用户态的字节码装载进内核并通过一个JIT编译步骤将程序的通用字节码转换为机器特定指令集以优化程序的执行速度。
在内核中运行时eBPF 程序通常会挂载到一个内核钩子hook上以便在特定的事件发生时被执行。例如可以将 eBPF 程序挂载到网络协议栈的某个位置以便在收到网络数据包时被执行。
最后eBPF 程序还需要经过内核安全机制的检查。这是为了确保 eBPF 程序不会破坏内核的稳定性和安全性。在检查过程中内核会对 eBPF 程序的代码进行分析以确保它不会进行恶意操作如系统调用、内存访问等。如果 eBPF 程序通过了内核安全机制的检查它就可以在内核中正常运行了。在运行过程中eBPF 程序可以访问内核的数据结构并通过内核接口与其他组件进行交互。例如eBPF 程序可以捕获网络数据包并通过内核接口将它们转发给用户态的应用程序。总之eBPF 的工作原理是通过动态加载、执行和检查无损编译过的代码来实现的。 3.环境介绍
名称版本linux版本centos8.54.18.0-348.el8.x86_64DM88.1.4.27pythonPython 3.6.8
4.安装环境
4.1检查环境 CONFIG_DEBUG_INFO_BTFy必须项否则就是操作系统不支持 [rootlocalhost opt]# uname -r
4.18.0-348.el8.x86_64
[rootlocalhost opt]# cat /boot/config-uname -r | grep CONFIG_DEBUG_INFO_BTF
CONFIG_DEBUG_INFO_BTFy4.2安装依赖包
[rootlocalhost opt]# dnf install -y bison cmake ethtool flex git iperf3 libstdc-devel python3-netaddr python3-pip gcc gcc-c make zlib-devel elfutils-libelf-devel
[rootlocalhost opt]# dnf install -y clang clang-devel llvm llvm-devel llvm-static ncurses-devel
[rootlocalhost opt]# dnf -y install netperf
[rootlocalhost opt]# pip3 install pyroute2
[rootlocalhost opt]# ln -s /usr/bin/python3 /usr/bin/python4.3安装并编译bcc
[rootlocalhost opt]# git clone https://github.com/iovisor/bcc.git
[rootlocalhost opt]# mkdir bcc-build
[rootlocalhost opt]# cd bcc-build/
[rootlocalhost opt]# cmake ../bcc -DCMAKE_INSTALL_PREFIX/usr -DENABLE_LLVM_SHARED1
[rootlocalhost opt]# make -j10
[rootlocalhost opt]# make install 4.4添加环境变量
安装后可以将 bcc 目录添加到$PATH可以将其添加到 ~/.bashrc
[rootlocalhost opt]# vim ~/.bashrc
bcctools/usr/share/bcc/tools
export PATH$bcctools:$PATH
[rootlocalhost opt]# source ~/.bashrc4.5安装DM并初始化实例
此步骤忽略
5.思路
5.1模拟阻塞场景
建表sql
create table lock_test01(id int primary key, name varchar(20));
create table lock_test02(id int primary key, name varchar(20));insert into lock_test01(id, name) values(1, 1cheng);
insert into lock_test01(id, name) values(2, 1gao);insert into lock_test02(id, name) values(1, 2cheng);
insert into lock_test02(id, name) values(2, 2gao);阻塞场景
-- Session A 执行insert 不提交
insert into SYSDBA.LOCK_TEST01(ID, NAME) VALUES(3, 3zzzz);
-- Session B 执行insert 会发生阻塞
insert into SYSDBA.LOCK_TEST01(ID, NAME) VALUES(3, 4zzzz);5.2判断堆栈中的核心函数
下面的堆栈是阻塞SQL的线程堆栈
Thread 127 (Thread 0x7fb29dfeb700 (LWP 19089)):
#0 0x00007fb64d8a77e8 in pthread_cond_timedwaitGLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x0000000000752f72 in os_event2_wait_timeout (eventevententry0x7fb6315e1fb0, s_times_timeentry30) at /home/dmops/build/svns/1725521374498/os/osevent2.c:303
#2 0x0000000001e571cb in uevent_wait_timeout (envenventry0x7fb29dfe6020, eventevententry0x7fb6315e1fa8, s_times_timeentry30) at /home/dmops/build/svns/1725521374498/knl/uevent.c:111
#3 0x0000000000ccc186 in trx4_waiting_timeout (envenventry0x7fb29dfe6020, trxtrxentry0x7fb6315e0898, w_timew_timeentry3) at /home/dmops/build/svns/1725521374498/trx/trx4.c:14642
#4 0x0000000000ccc32a in trx4_waiting_interval (envenventry0x7fb29dfe6020, trxtrxentry0x7fb6315e0898, s_times_timeentry0) at /home/dmops/build/svns/1725521374498/trx/trx4.c:14217
#5 0x0000000000cd69e4 in trx4_waiting (envenventry0x7fb29dfe6020, trxtrxentry0x7fb6315e0898, s_times_timeentry0) at /home/dmops/build/svns/1725521374498/trx/trx4.c:14383
#6 0x00000000018446f0 in nins2_check_second_unique (memobjmemobjentry0x7fb2e000d3b8, trxtrxentry0x7fb6315e0898, ptxptxentry0x7fb29dfdd2c0, pbcpbcentry0x7fb29dfdcf30, bcurbcurentry0x7fb29dfdce90, keykeyentry0x7fb34c417a60, descdescentry0x7fb2ee14c098, tableidtableidentry1017, search_modesearch_modeentry2, need_lock_rowneed_lock_rowentry1, cflt_rowidcflt_rowidentry0x0, need_modifyneed_modifyentry0x7fb29dfdfb6c, pll_index_fillpll_index_fillentry0) at /home/dmops/build/svns/1725521374498/op/nins2.c:8616
#7 0x0000000001847789 in nins2_second_unique_search_and_check (memobjmemobjentry0x7fb2e000d3b8, trxtrxentry0x7fb6315e0898, ptxptxentry0x7fb29dfdd2c0, pbcpbcentry0x7fb29dfdcf30, indexindexentry0x7fb2ee14bd70, tabletableentry0x7fb2ee14aae8, keykeyentry0x7fb34c417a60, need_lock_rowneed_lock_rowentry1, search_modesearch_modeentry2, descdescentry0x7fb2ee14c098, rec_len19, rowidrowidentry4, ign_cfltign_cfltentry0, cflt_rowidcflt_rowidentry0x0, need_modifyneed_modifyentry0x7fb29dfdfb6c, bcurbcurentry0x7fb29dfdce90, pll_index_fillpll_index_fillentry0) at /home/dmops/build/svns/1725521374498/op/nins2.c:10126
#8 0x0000000001848fd9 in nins2_second_unique_insert_low (memobjmemobjentry0x7fb2e000d3b8, trx0x7fb6315e0898, ptx0x7fb29dfdd2c0, pbc0x7fb29dfdcf30, indexindexentry0x7fb2ee14bd70, table0x7fb2ee14aae8, tupletupleentry0x7fb34c417998, keykeyentry0x7fb34c417a60, need_lock_rowneed_lock_rowentry1, search_modesearch_modeentry2, n_rol_len_fixed_partn_rol_len_fixed_partentry45, rowidrowidentry4, with_trxidwith_trxidentry0, ign_cfltign_cfltentry0, cflt_rowidcflt_rowidentry0x0, need_modifyneed_modifyentry0x7fb29dfdfb6c, bcurbcurentry0x7fb29dfdce90, pll_index_fillpll_index_fillentry0, org_trx_id_outorg_trx_id_outentry0x0) at /home/dmops/build/svns/1725521374498/op/nins2.c:10222
#9 0x00000000018492c5 in nins2_second_unique_insert (memobjmemobjentry0x7fb2e000d3b8, trxoptimized out, ptxoptimized out, pbcoptimized out, indexindexentry0x7fb2ee14bd70, tableoptimized out, tuple0x7fb34c417998, key0x7fb34c417a60, need_lock_row1, search_mode2, n_rol_len_fixed_part45, rowid4, ign_cflt0, cflt_rowid0x0, need_modify0x7fb29dfdfb6c, bcur0x7fb29dfdce90, pll_index_fill0) at /home/dmops/build/svns/1725521374498/op/nins2.c:10267
#10 0x0000000001849a39 in nins2_index_insert_entry_low (memobjmemobjentry0x7fb2e000d3b8, trxoptimized out, ptxptxentry0x7fb29dfdd2c0, pbcpbcentry0x7fb29dfdcf30, indexindexentry0x7fb2ee14bd70, tupletupleentry0x7fb34c417998, key0x7fb34c417998, keyentry0x7fb34c417a60, need_lock_row1279359584, need_lock_rowentry1, search_mode1, search_modeentry2, n_rol_len_fixed_part2, n_rol_len_fixed_partentry45, rowid0x7fb20000002d, rowidentry0x7fb29dfdff50, ign_cflt4, ign_cfltentry0, cflt_rowidcflt_rowidentry0x0, need_modify0x0, need_modifyentry0x7fb29dfdfb6c, table0x7fb29dfdfb6c, tableentry0x7fb2ee14aae8, with_rowid2650656400, with_rowidentry0, vm_node0x7fb300000000, vm_nodeentry0x7fb34c416fd0, bcurbcurentry0x7fb29dfdce90, pll_index_fill0) at /home/dmops/build/svns/1725521374498/op/nins2.c:10508
#11 0x000000000185c1f8 in nins2_index_insert_entry (env0x7fb29dfe6020, memobj0x7fb2e000d3b8, vmvmentry0x7fb2e000d350, indexindexentry0x7fb2ee14bd70, tuple0x7fb34c417998, keykeyentry0x7fb34c417a60, need_lock_low1, n_rol_len_fixed_part45, rowidrowidentry0x7fb29dfdff50, ign_cfltign_cfltentry0, cflt_rowidcflt_rowidentry0x0, need_modifyneed_modifyentry0x7fb29dfdfb6c, table0x7fb2ee14aae8, with_rowid0, vm_nodevm_nodeentry0x7fb34c416fd0) at /home/dmops/build/svns/1725521374498/op/nins2.c:11889
#12 0x000000000185ceea in nins2_exec_insert_low (nins2_vmnins2_vmentry0x7fb34c416fd0) at /home/dmops/build/svns/1725521374498/op/nins2.c:12796
#13 0x000000000185da5f in nins2_exec_insert (nins2_vmnins2_vmentry0x7fb34c416fd0) at /home/dmops/build/svns/1725521374498/op/nins2.c:13492
#14 0x000000000186077f in nins2_exec (nins2_vm0x7fb34c416fd0) at /home/dmops/build/svns/1725521374498/op/nins2.c:18904
#15 0x000000000195eab8 in vm_run_low (vmvmentry0x7fb2e000d350) at /home/dmops/build/svns/1725521374498/op/vm.c:6115
#16 0x000000000195ef30 in vm_run (vmvmentry0x7fb2e000d350) at /home/dmops/build/svns/1725521374498/op/vm.c:6196
#17 0x000000000195f080 in vm_run_pln_low (envenventry0x7fb29dfe6020, stmtstmtentry0x7fb2e000c8f0, plnplnentry0x7fb2ee138ac8, ret_ident_flagret_ident_flagentry0 \000, n_ret_coln_ret_colentry0, ret_col_identret_col_idententry0x0, err_descerr_descentry0x0) at /home/dmops/build/svns/1725521374498/op/vm.c:11602
#18 0x0000000001fae1d0 in ntsk_process_exec_low (envenventry0x7fb29dfe6020, stmt0x7fb2e000c8f0, plnplnentry0x7fb2ee138ac8, ret_ident_flagret_ident_flagentry0 \000, n_ret_coloptimized out, ret_col_ident0x0, dlck_repreparedlck_reprepareentry0x7fb29dfe46bc) at /home/dmops/build/svns/1725521374498/mgr/ntsk.c:12603
#19 0x0000000001fb2256 in ntsk_process_prepare_and_exec (envenventry0x7fb29dfe6020, sesssessentry0x7fb2e00110f0, msg_inmsg_inentry0x7fb2e00029a8 , stmtsql_outstmtsql_outentry0x7fb29dfe57c8) at /home/dmops/build/svns/1725521374498/mgr/ntsk.c:13063
#20 0x0000000001fde785 in ntsk_process_cop (env0x7fb29dfe6020, taskoptimized out) at /home/dmops/build/svns/1725521374498/mgr/ntsk.c:21389
#21 0x0000000001e5b755 in uthr_db_main_for_sess (sess20x7fb2e00110f0) at /home/dmops/build/svns/1725521374498/knl/uthr.c:1367
#22 0x00007fb64d8a117a in start_thread () from /lib64/libpthread.so.0
#23 0x00007fb64ccb5dc3 in clone () from /lib64/libc.so.6头部 pthread_cond_timedwait 和 uevent_wait_timeout 都是自定义函数而不是标准库提供的系统函数。
2) os_event2_wait_timeout这是一个封装函数它调用 pthread_cond_timedwait 并接受一个事件和超时时间30秒。 uevent_wait_timeout这个函数在内核中用于等待 uevent 事件传入的参数包括环境指针和事件指针以及超时时间。 trx4_waiting_timeout这个函数可能是一个事务相关的等待函数传入了环境、事务和等待时间3秒
根据函数命名以及堆栈的含义pthread_cond_timedwait 和 uevent_wait_timeout 肯定是代码底层的通用函数所以初步判断SQL阻塞使用 trx4_waiting_timeout 函数就可以 我们此时进行测试。
6.编写代码
[rootlocalhost opt]# vim ebpf_trx.pyfrom bcc import BPF# 定义 eBPF 程序
bpf_text
#include uapi/linux/ptrace.h
#include linux/sched.h
#include linux/timekeeping.hBPF_HASH(start_time, u64);// 处理 uprobe 事件
int trace_ntsk_process_cop(struct pt_regs *ctx) {u64 pid_tgid bpf_get_current_pid_tgid(); // 获取 PID 和 TGIDu64 thread_id pid_tgid 32; // 获取线程号u64 timestamp bpf_ktime_get_ns();// 记录开始时间start_time.update(pid_tgid, timestamp);bpf_trace_printk(ntsk_process_cop called: pid%d, thread_id%d, timestamp%llu, pid_tgid 0xFFFFFFFF, thread_id, timestamp);return 0;
}// 处理返回事件
int trace_ret_ntsk_process_cop(struct pt_regs *ctx) {u64 pid_tgid bpf_get_current_pid_tgid(); // 获取 PID 和 TGIDu64 thread_id pid_tgid 32; // 获取线程号u64 *start_ts start_time.lookup(pid_tgid);if (start_ts ! 0) {u64 end_time bpf_ktime_get_ns();u64 total_time end_time - *start_ts;u64 total_time_ms total_time / 1000000;bpf_trace_printk(ntsk_process_cop exited: pid%d, thread_id%d, total_time%llu ms, pid_tgid 0xFFFFFFFF, thread_id, total_time_ms);start_time.delete(pid_tgid);}return 0;
}
# 加载 eBPF 程序
b BPF(textbpf_text)# 设置 uprobe
b.attach_uprobe(name/opt/dmdbms/bin/dmserver, symtrx4_waiting_timeout, fn_nametrace_ntsk_process_cop)
b.attach_uretprobe(name/opt/dmdbms/bin/dmserver, symtrx4_waiting_timeout, fn_nametrace_ret_ntsk_process_cop)# 输出跟踪信息
print(正在跟踪 uprobe... 按 Ctrl-C 结束。)# 输出追踪信息
b.trace_print() 代码解释 BPF_HASH(start_time, u64); 创建一个哈希表 start_time键类型为 u64用于存储每个进程的开始时间。它通过 PID进程标识符来索引bpf_get_current_pid_tgid(): 获取当前进程的 PID 和线程 IDattach_uprobe ()表示将钩子附加到dmserver的trx4_waiting_timeout函数的头部位置attach_uretprobe()表示将钩子附加到dmserver的trx4_waiting_timeout函数的结尾位置在函数开始的时候存储开始时间在函数结尾时相减就是执行该函数的耗时并输出PID 以及 threadID即可。
7.验证代码
[rootlocalhost opt]# python ebpf_trx.py 验证结果说明 运行程序以后会发现只有当SQL阻塞的时候才会输出信息进程号、线程号、函数的执行耗时 说明对trx4_waiting_timeout函数添加钩子是没有问题运行时会发现每隔3S输出一次添加符号文件的堆栈可以看到trx4_waiting_timeout函数的w_time3这块可以一一对应。有了这些信息就能够做很多事情比如说将信息推送到监控平台等。
8.总结与思考
利用ebpf技术在不登录数据库的情况下通过对数据库的函数添加钩子实时的对数据库是否存在阻塞判断现有的监控逻辑都是新建数据库用户执行SQL语句来判断阻塞情况告警的实时性取决于监控的周期频率而使用ebpf技术能够解决这个痛点ebpf有多种实现方式这里便于理解测试的话 使用python语言内置c语言的形式进行了说明。涉及到生产环境应该是使用go语言或者c语言去做能够有效避免源码泄露等问题如给sql线程添加钩子有代sql变量的偏移量的话就能够不登录数据库的情况下捕获到慢SQL就能够有效的解决很多问题了有待探究