[转帖]程序员的平行宇宙 —— eBPF 系统级跟踪技术简单入门

程序员,平行,宇宙,ebpf,系统,跟踪,技术,简单,入门 · 浏览次数 : 0

小编点评

**Linux 历史悠久** * 许多技术用于跟踪系统命令的执行,包括 eBPF、perf 等工具。 * eBPF 是监听函数调用并抽象为事件源的技术。 * 监听整个系统的 bash 执行命令可以通过 uprobe 方法进行。 * cachestat 脚本通过 kprobe 技术监听内核中的函数。 * tcpretransTIMEPIDIP 监控 TCP 丢包(重传)。 **eBPF 的应用场景** * eBPF 可用于各种任务,包括: * 跟踪系统命令的执行 * 分析系统性能 * 定位数据库 IO 问题 * 监控 TCP 丢包 * eBPF 与其他工具如 perf 类似,但具有更好的性能。 **eBPF 与 perf 的比较** | 特性 | eBPF | perf | |---|---|---| | 性能 | 高 | 低 | | 可扩展性 | 高 | 低 | | 使用场景 | 高性能任务 | 低性能任务 |

正文

https://blog.mygraphql.com/zh/posts/low-tec/trace/trace-quick-start/

 

程序员的平行宇宙

程序员有两个世界:

  1. 一个是编码世界,我们很容易认为,我们考虑了一切,也完成了一切的代码。
  2. 然后是运行世界,我们发现,无论我们多么的严谨和考虑一切,世界总是有异常。异常就好像电磁波,一开始,我们只能通过它引发的结果而发现它,而不能直接观察。因为它总出现在那些黑暗的角落,如果我们手中没有电简和电磁波示波器,一切只能依靠猜测和迷信。最后,我们进入了一个用猜测驱动的世界。有时候,我们运气好,猜中了。有时候,我们只能在 release 前多上香。

It is a capital mistake to theorize before one has data. Insensibly one begins to twist facts to suit theories, instead of theories to suit facts.

– Sherlock Holmes in “A Scandal in Bohemia” by Sir Arthur Conan Doyle

在获得数据之前先进行理论分析是一个重大错误。 荒谬的是,人们开始扭曲事实以适应理论,而不是理论去适应事实。

—— 福尔摩斯(Sherlock Holmes)在亚瑟·柯南·道尔爵士(Arthur Conan Doyle)创作的《波西米亚丑闻》

系统跟踪技术

当我们发现应用程序的功能或性能不如预期时,常用应用或操作系统跟踪的方法来定位问题。这里的跟踪包括以下方法:

  1. 非生产环境的 Debug —— 如 java remote debug/gdb/go-delve
  2. 生产环境可用的跟踪 —— 通过 probe(探针)等式方法监控程序内部,对应用的性能影响有限

本文讨论第二种方法 。

一直以来,如何在资源受限的生产环境,或性能测试环境中跟踪有问题的应用程序都是一个难题。最常见的一个题目是,我的程序慢在哪个地方?聪明的程序员和 DevOps 们不断发明了各种工具:DTrace / SystemTAP / perf ,今天我要介绍的是 eBPF 技术和它的工具栈。

一切从函数说起

大家知道,即使的编程语言从汇编发展到现在的Java/GO,有一个基本的编程单位的不变的 —— 函数(方法)。即使我们以为已经用了 OOP(面向对象)、AOP、Serverless ,函数依然是编译器、CPU 指令(X86下的 callq)内部的单位,只是内部的函数名字和我们在源码中看到的名字有一定的前后缀等映射关系。

一般,应用或内核中会存在一个符号表(Symbol Tables)记录了应用中的函数和其在应用中的地址

通过跟踪这些函数的调用信息,如调用入参、返回值、调用次数,响应时间分布,就可以为问题定位提供明确和可信的方向。下面是一个符号表的例子:

1
2
3
$ readelf --dyn-syms /usr/bin/bash | grep 'readline$'
   882: 00000000000b8520   154 FUNC    GLOBAL DEFAULT   16 readline
  1239: 00000000000873a0  1963 FUNC    GLOBAL DEFAULT   16 initialize_readline

发现,bash 有一个内部函数readline。bash 通过它读取每个行 shell 命令。只要监控这个函数的入参,就可以监控系统中的所有 bash 发起的命令。

如何监听函数

在 Java 世界,可以通过 java instrument 来实现函数的修改或监听。在更广义的世界 CPU 指令世界,有相近的方法去修改或监听CPU指令。之前说了,一般,源码中的函数,是会编译为一个X86下的 callq 指令。只要我们替换函数的入口为一个断点指令(int3);然后在断点处理程序中调用定制的监听程序;之后再调用实际的原程序。

如 trace 前的 bash 进程 :

# gdb -p 31817
[...]
(gdb) disas readline
Dump of assembler code for function readline:
0x000055f7fa995610 <+0>:
<rl_pending_input> cmpl $0xffffffff,0x2656f9(%rip) # 0x55f7fabfad10
0x000055f7fa995617 <+7>: push %rbx
0x000055f7fa995618 <+8>: je 0x55f7fa99568f <readline+127>
0x000055f7fa99561a <+10>: callq 0x55f7fa994350 <rl_set_prompt>
0x000055f7fa99561f <+15>: callq 0x55f7fa995300 <rl_initialize>
0x000055f7fa995624 <+20>: mov
<rl_prep_term_function>
0x000055f7fa99562b <+27>: test
0x261c8d(%rip),%rax
# 0x55f7fabf72b8
%rax,%rax
[...]

用 uprobes 技术 trace 了 readline 函数后:

# gdb -p 31817
[...]
(gdb) disas readline
Dump of assembler code for function readline:
>>>> 0x000055f7fa995610 <+0>: int3 0x000055f7fa995611 <+1>: cmp $0x2656f9,%eax <<<<
0x000055f7fa995616 <+6>: callq *0x74(%rbx)
0x000055f7fa995619 <+9>: jne 0x55f7fa995603 <rl_initialize+771>
0x000055f7fa99561b <+11>: xor
%ebp,%ebp
0x000055f7fa99561d <+13>: (bad)
0x000055f7fa99561e <+14>: (bad)
0x000055f7fa99561f <+15>: callq 0x55f7fa995300 <rl_initialize>
0x261c8d(%rip),%rax
# 0x55f7fabf72b8
[...]

Linux 的历史悠久。有好几种的 trace 技术:

技术需源程序预留用户进程/内核
kprobes NO 内核
uprobes NO 用户进程
Tracepoints YES 内核
USDT YES 用户进程

而 eBPF 就是使用上面的技术,监听函数的调用,然后抽象为一个事件源(Event Sources):

eBPF Datasource,来源: [BPF Performance Tools]

工具集

eBPF 打开了跟踪的大門。但門槛太高,于是,我们需要一些封装好的库或工具集。比较成熟的有 BCC 和 ebpftrace。如果你的的 Linux 发行版本中足够新,这两个工具都可以直接安装。

例子

作为一个自吹为干货,实为抄袭😅的文章,还是上点例子好。

监听整个系统的 bash 执行的命令

假设我们是 bash 的开发,或者,我们了解 bash 的源码,已经知道,bash 通过自己的 readline 函数读取终端的命令。这时,只需要用 uprobe 方法监听 readline 函数的返回值。

以下假设我们在开始监听后,在其它终端中输入了ls / 和 find / 命令。

1
2
3
4
5
6
$ bpftrace -e 'uretprobe:/bin/bash:readline { printf("%s\n", str(retval)); }'
Attaching 1 probe...
ls /
find /
...
^C

你可以通过 bpftrace -l 'uprobe:/bin/bash' 或 readelf 了解一个可执行文件或 so 文件的函数列表。

监听系统的缓存的命中率

BCC 的 cachestat 脚本,通过 kprobe 技术,监听内核的 add_to_page_cache_lru等函数,可以计算出缓存命中率。这个功能在定位数据库 IO 问题时,由为实用(我曾经用它定位 Cassandra 数据库的IO问题)。

1
2
3
4
5
6
7
8
# cachestat
HITS MISSES BUFFERS_MB CACHED_MB
53401 2755
DIRTIES HITRATIO
20953 95.09% 14 90223
49599 4098 21460 92.37% 14 90230
16601 2689 61329 86.06% 14 90381
15197 2477 58028 85.99% 14 90522

监听 TCP 丢包(重传)

无论现代网络硬件和软件如何发展,丢包分析是个永远逃不了的 DevOps 工作。对于 TCP,部分丢包(不是全部对应)可以直接反映在 TCP 重传上。这时,监听内核的 TCP 重传对由为重要。

1
2
3
4
5
6
7
8
# tcpretrans
TIME
PID
IP LADDR:LPORT T> RADDR:RPORT STATE
01:55:05 0 4 10.153.223.157:22 R> 69.53.245.40:34619 ESTABLISHED
01:55:05 0 4 10.153.223.157:22 R> 69.53.245.40:34619 ESTABLISHED
01:55:17 0 4 10.153.223.157:22 R> 69.53.245.40:22957 ESTABLISHED
[...]

可见,列出的发生重传时,丢包的 TCP 连接的双端的 IP 和端口。

最后

以上是最简单的例子。eBPF 世界,才刚开始。后面,我计划说说 eBPF 的应用场景,和它与其它工具如 perf 的比较。再见!Keep tracing !

参考

[BPF Performance Tools]

与[转帖]程序员的平行宇宙 —— eBPF 系统级跟踪技术简单入门相似的内容:

[转帖]程序员的平行宇宙 —— eBPF 系统级跟踪技术简单入门

https://blog.mygraphql.com/zh/posts/low-tec/trace/trace-quick-start/ 程序员的平行宇宙 程序员有两个世界: 一个是编码世界,我们很容易认为,我们考虑了一切,也完成了一切的代码。 然后是运行世界,我们发现,无论我们多么的严谨和考虑一切

[转帖]一文带你掌握 Redis

https://www.bbsmax.com/A/8Bz8AKGkJx/ 一、摘要 谈起 Redis,相信大家都不会陌生,做过云平台开发的程序员多多少少会接触到它,Redis 英文全称:Remote Dictionary Server,也被称之为远程字典服务。 从官方的定义看,Redis 是一款开源

[转帖]性能优化 YYDS - Brendan Gregg 与 Intel.com 的故事

https://www.modb.pro/db/421309 译者序 金庸笔下的《鹿鼎记》有: !! 平生不识陈近南,便称英雄也枉然 现代的认真搞技术的后端程序员,应该也有一句: !! 平生不识 Brendan Gregg,便呆 BAT 也 SoSo 从 2016 年开始,做一个 JVM 调优开始,

[转帖]Linux 命令详解(三)./configure、make、make install 命令

https://www.cnblogs.com/tinywan/p/7230039.html 这些都是典型的使用GNU的AUTOCONF和AUTOMAKE产生的程序的安装步骤 一、基本信息 1、./configure 是用来检测你的安装平台的目标特征的。比如它会检测你是不是有CC或GCC,并不是需要

[转帖]jconsole远程监控认证,java远程监控,jmx监控应用,jmx ssl配置,jconsole ssl连接远程应用

知识普及 jmx JMX(java Management Extensions)是一个Java平台的管理和监控接口。任何程序,只要按JMX规范访问这个接口,就可以获取所有管理与监控信息,jconsole与Java VisualVM等常见监测工具都是基于jmx,JMX不但可以用于管理JVM,还可以管理

[转帖]pyinstaller实现将python程序打包成exe文件

https://www.cnblogs.com/blogzyq/p/13939739.html 如果我们想要在一个没有python以及很多库环境的电脑上使用我们的小程序该怎么办呢? 我们想到,在Windows平台可以将程序打包成exe可执行文件,而pyinstaller就可以帮我们将程序打包成exe

[转帖]pgbench 使用介绍及示例

pgbench 使用介绍及示例 https://www.cnblogs.com/cqdba/ 1.pgbench概要 pgbench是一种在PostgreSQL上运行基准测试的简单程序, 它是pg自带的工具; 它可能在并发的数据库会话中一遍一遍地运行相同序列的 SQL 命令,并且计算平均事务率(每秒

[转帖]如何优雅的使用 Systemd 管理服务

https://zhuanlan.zhihu.com/p/271071439 背景:我们在构建 Kubernetes 容器化平台时,会在节点上部署各种 agent ,虽然容器化当道的今天很多程序可以直接采用 docker 方式进行运行,但我们在整个集群内部仍然大量使用了 systemd 来管理基础服

[转帖]Windows平台下使用 Rclone 挂载 OneDrive 为本地硬盘

https://zhuanlan.zhihu.com/p/139200172 Rclone (rsync for cloud storage) 是一个命令行程序,用于同步文件和目录,支持常见的 Amazon Drive 、Google Drive 、OneDrive 、Dropbox 等云存储。本文

[转帖]一个故事看懂计算机操作系统的进化史

https://www.cnblogs.com/xuanyuan/p/14749838.html 计算机 很久很久以前,有一台机器,体型巨大,每秒钟可以进行几千次的加法运算,名震一时,人类给它取了个名字:计算机。 除了加法,它还能计算平方、立方、正弦、余弦,比人类的大脑算得快多了。 许多程序慕名而来