Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
Service Mesh架构新技能之eBPF入门与实践_创想鸟

Service Mesh架构新技能之eBPF入门与实践

在分享这篇文章之前,先简单和大家说下背景。在之前的文章中作者分享了一些关于service mesh微服务架构的文章,在service mesh架构中需要通过sidecar代理的方式对应用容器流量进行劫持,并以此实现微服务治理相关的各种能力。但这种sidecar方式在微服务数量过多时会造成系统性能的降低,因为sidecar本质上来说,也是通过用户代码实现的网络代理来进行流量管控的。而ebpf则是一种替代sidecar的新式解决方案,它存在于操作系统的内核层级,在性能上表现更优。因此目前关于service mesh微服务架构的技术方案开始逐步趋向于使用ebpf来替代原先的像envoy这样的sidecar代理。本文的内容将详细介绍ebpf的前世今生,具体如下:

1

技术背景

eBPF 源于 BPF,本质上是处于内核中的一个高效与灵活的虚类虚拟机组件,以一种安全的方式在许多内核 hook 点执行字节码。BPF 最初的目的是用于高效网络报文过滤,经过重新设计,eBPF 不再局限于网络协议栈,已经成为内核顶级的子系统,演进为一个通用执行引擎。

开发者可基于 eBPF 开发性能分析工具、软件定义网络、安全等诸多场景。本文将介绍 eBPF 的前世今生,并构建一个 eBPF 环境进行开发实践,文中所有的代码可以在我的 GitHub[1] 中找到。

发展历史

BPF,是类 Unix 系统上数据链路层的一种原始接口,提供原始链路层封包的收发。1992 年,Steven McCanne 和 Van Jacobson 写了一篇名为《The BSD Packet Filter: A New Architecture for User-level Packet Capture[2]》的论文。在文中,作者描述了他们如何在 Unix 内核实现网络数据包过滤,这种新的技术比当时最先进的数据包过滤技术快 20 倍。

Service Mesh架构新技能之eBPF入门与实践

BPF 在数据包过滤上引入了两大革新:

一个新的虚拟机 (VM) 设计,可以有效地工作在基于寄存器结构的 CPU 之上应用程序使用缓存只复制与过滤数据包相关的数据,不会复制数据包的所有信息,这样可以最大程度地减少BPF 处理的数据

由于这些巨大的改进,所有的 Unix 系统都选择采用 BPF 作为网络数据包过滤技术,直到今天,许多 Unix 内核的派生系统中(包括 Linux 内核)仍使用该实现。tcpdump 的底层采用 BPF 作为底层包过滤技术,我们可以在命令后面增加 -d 来查看 tcpdump 过滤条件的底层汇编指令。

代码语言:javascript代码运行次数:0运行复制

$ tcpdump -d 'ip and tcp port 8080'(000) ldh      [12](001) jeq      #0x800           jt 2 jf 12(002) ldb      [23](003) jeq      #0x6             jt 4 jf 12(004) ldh      [20](005) jset     #0x1fff          jt 12 jf 6(006) ldxb     4*([14]&0xf)(007) ldh      [x + 14](008) jeq      #0x1f90          jt 11 jf 9(009) ldh      [x + 16](010) jeq      #0x1f90          jt 11 jf 12(011) ret      #262144(012) ret      #0

2014 年初,Alexei Starovoitov 实现了 eBPF(extended Berkeley Packet Filter)。经过重新设计,eBPF 演进为一个通用执行引擎,可基于此开发性能分析工具、软件定义网络等诸多场景。

eBPF 最早出现在 3.18 内核中,此后原来的 BPF 就被称为经典 BPF,缩写 cBPF(classic BPF),cBPF 现在已经基本废弃。现在,Linux 内核只运行 eBPF,内核会将加载的 cBPF 字节码透明地转换成 eBPF 再执行。

eBPF 与 cBPF

eBPF 新的设计针对现代硬件进行了优化,所以 eBPF 生成的指令集比旧的 BPF 解释器生成的机器码执行得更快。扩展版本也增加了虚拟机中的寄存器数量,将原有的 2 个 32 位寄存器增加到 10 个 64 位寄存器。

由于寄存器数量和宽度的增加,开发人员可以使用函数参数自由交换更多的信息,编写更复杂的程序。总之,这些改进使 eBPF 版本的速度比原来的 BPF 提高了 4 倍。

维度

cBPF

eBPF

内核版本

Linux 2.1.75(1997 年)

Linux 3.18(2014 年)[4.x for kprobe/uprobe/tracepoint/perf-event]

寄存器数目

2 个:A,X

10个:R0–R9,另外 R10 是一个只读的帧指针R0:eBPF 中内核函数的返回值和退出值R1 – R5:eBF 程序在内核中的参数值R6 – R9:内核函数将保存的被调用者callee保存的寄存器R10:一个只读的堆栈帧指针

寄存器宽度

32 位

64 位

存储

16 个内存位: M[0–15]

512 字节堆栈,无限制大小的 map 存储

限制的内核调用

非常有限,仅限于 JIT 特定

有限,通过 bpf_call 指令调用

目标事件

数据包、 seccomp-BPF

数据包、内核函数、用户函数、跟踪点 PMCs 等

R0:eBPF 中内核函数的返回值和退出值R1 – R5:eBF 程序在内核中的参数值R6 – R9:内核函数将保存的被调用者callee保存的寄存器R10:一个只读的堆栈帧指针

寄存器宽度32 位64 位存储16 个内存位: M[0–15]512 字节堆栈,无限制大小的 map 存储限制的内核调用非常有限,仅限于 JIT 特定有限,通过 bpf_call 指令调用目标事件数据包、 seccomp-BPF数据包、内核函数、用户函数、跟踪点 PMCs 等

2014 年 6 月,eBPF 扩展到用户空间,这也成为了 BPF 技术的转折点。正如 Alexei 在提交补丁的注释中写到:「这个补丁展示了 eBPF 的潜力」。当前,eBPF 不再局限于网络栈,已经成为内核顶级的子系统。

eBPF 与内核模块

对比 Web 的发展,eBPF 与内核的关系有点类似于 JavaScript 与浏览器内核的关系,eBPF 相比于直接修改内核和编写内核模块提供了一种新的内核可编程的选项。eBPF 程序架构强调安全性和稳定性,看上去更像内核模块,但与内核模块不同,eBPF 程序不需要重新编译内核,并且可以确保 eBPF 程序运行完成,而不会造成系统的崩溃。

维度

Linux 内核模块

eBPF

kprobes/tracepoints

支持

支持

安全性

可能引入安全漏洞或导致内核 Panic

通过验证器进行检查,可以保障内核安全

内核函数

可以调用内核函数

只能通过 BPF Helper 函数调用

编译性

需要编译内核

不需要编译内核,引入头文件即可

运行

基于相同内核运行

基于稳定 ABI 的 BPF 程序可以编译一次,各处运行

与应用程序交互

打印日志或文件

通过 perf_event 或 map 结构

数据结构

丰富性

一般丰富

入门门槛

升级

需要卸载和加载,可能导致处理流程中断

原子替换升级,不会造成处理流程中断

内核内置

视情况而定

内核内置支持

eBPF 架构

eBPF 分为用户空间程序和内核程序两部分:

用户空间程序负责加载 BPF 字节码至内核,如需要也会负责读取内核回传的统计信息或者事件详情内核中的 BPF 字节码负责在内核中执行特定事件,如需要也会将执行的结果通过 maps 或者 perf-event 事件发送至用户空间其中用户空间程序与内核 BPF 字节码程序可以使用 map 结构实现双向通信,这为内核中运行的 BPF 字节码程序提供了更加灵活的控制

eBPF 整体结构图如下:

Service Mesh架构新技能之eBPF入门与实践

用户空间程序与内核中的 BPF 字节码交互的流程主要如下:

1、使用 LLVM 或者 GCC 工具将编写的 BPF 代码程序编译成 BPF 字节码

2、使用加载程序 Loader 将字节码加载至内核

3、内核使用验证器(Verfier) 组件保证执行字节码的安全性,以避免对内核造成灾难,在确认字节码安全后将其加载对应的内核模块执行

4、内核中运行的 BPF 字节码程序可以使用两种方式将数据回传至用户空间:

maps 方式可用于将内核中实现的统计摘要信息(比如测量延迟、堆栈信息)等回传至用户空间;perf-event 用于将内核采集的事件实时发送至用户空间,用户空间程序实时读取分析。

eBPF 限制

eBPF 技术虽然强大,但是为了保证内核的处理安全和及时响应,内核中的 eBPF 技术也给予了诸多限制,当然随着技术的发展和演进,限制也在逐步放宽或者提供了对应的解决方案。

eBPF 程序不能调用任意的内核参数,只限于内核模块中列出的 BPF Helper 函数,函数支持列表也随着内核的演进在不断增加。

eBPF 程序不允许包含无法到达的指令,防止加载无效代码,延迟程序的终止。

eBPF 程序中循环次数限制且必须在有限时间内结束,这主要是用来防止在 kprobes 中插入任意的循环,导致锁住整个系统;解决办法包括展开循环,并为需要循环的常见用途添加辅助函数。Linux 5.3 在 BPF 中包含了对有界循环的支持,它有一个可验证的运行时间上限。

eBPF 堆栈大小被限制在 MAX_BPF_STACK,截止到内核 Linux 5.8 版本,被设置为 512;参见 include/linux/filter.h[3],这个限制特别是在栈上存储多个字符串缓冲区时:一个char[256]缓冲区会消耗这个栈的一半。目前没有计划增加这个限制,解决方法是改用 bpf 映射存储,它实际上是无限的。

代码语言:javascript代码运行次数:0运行复制

/* BPF program can access up to 512 bytes of stack space. */#define MAX_BPF_STACK 512

eBPF 字节码大小最初被限制为 4096 条指令,截止到内核 Linux 5.8 版本, 当前已将放宽至 100 万指令( BPF_COMPLEXITY_LIMIT_INSNS),参见:include/linux/bpf.h[4],对于无权限的BPF程序,仍然保留4096条限制 ( BPF_MAXINSNS );新版本的 eBPF 也支持了多个 eBPF 程序级联调用,虽然传递信息存在某些限制,但是可以通过组合实现更加强大的功能。

代码语言:javascript代码运行次数:0运行复制

#define BPF_COMPLEXITY_LIMIT_INSNS      1000000 /* yes. 1M insns */

2

eBPF 实战

在深入介绍 eBPF 特性之前,让我们 Get Hands Dirty,切切实实的感受 eBPF 程序到底是什么,我们该如何开发 eBPF 程序。随着 eBPF 生态的演进,现在已经有越来越多的工具链用于开发 eBPF 程序,在后文也会详细介绍:

基于 bcc 开发:bcc 提供了对 eBPF 开发,前段提供 Python API,后端 eBPF 程序通过 C 实现。特点是简单易用,但是性能较差。基于 libebpf-bootstrap 开发:libebpf-bootstrap 提供了一个方便的脚手架。基于内核源码开发:内核源码开发门槛较高,但是也更加切合 eBPF 底层原理,所以这里以这个方法作为示例。

内核源码编译

系统环境如下,采用PHP中文网 CVM,Ubuntu 20.04,内核版本 5.4.0。

代码语言:javascript代码运行次数:0运行复制

$ uname -aLinux VM-1-3-ubuntu 5.4.0-42-generic #46-Ubuntu SMP Fri Jul 10 00:24:02 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

首先安装必要依赖:

代码语言:javascript代码运行次数:0运行复制

sudo apt install -y bison build-essential cmake flex git libedit-dev pkg-config libmnl-dev    python zlib1g-dev libssl-dev libelf-dev libcap-dev libfl-dev llvm clang pkg-config    gcc-multilib luajit libluajit-5.1-dev libncurses5-dev libclang-dev clang-tools

一般情况下推荐采用 apt 方式的安装源码,安装简单而且只安装当前内核的源码,源码的大小在 200M 左右。

代码语言:javascript代码运行次数:0运行复制

# apt-cache search linux-source# apt install linux-source-5.4.0

源码安装至 /usr/src/ 目录下。

代码语言:javascript代码运行次数:0运行复制

$ ls -hltotal 4.0Kdrwxr-xr-x 4 root root 4.0K Nov  9 13:22 linux-source-5.4.0lrwxrwxrwx 1 root root   45 Oct 15 10:28 linux-source-5.4.0.tar.bz2 -> linux-source-5.4.0/linux-source-5.4.0.tar.bz2$ tar -jxvf linux-source-5.4.0.tar.bz2$ cd linux-source-5.4.0$ cp -v /boot/config-$(uname -r) .config # make defconfig 或者 make menuconfig$ make headers_install$ make modules_prepare$ make scripts     # 可选$ make M=samples/bpf  # 如果配置出错,可以使用 make oldconfig && make prepare 修复

编译成功后,可以在 samples/bpf 目录下看到一系列的目标文件和二进制文件。

Hello World

前面说到 eBPF 通常由内核空间程序和用户空间程序两部分组成,现在 samples/bpf 目录下有很多这种程序,内核空间程序以 _kern.c 结尾,用户空间程序以 _user.c 结尾。先不看这些复杂的程序,我们手动写一个 eBPF 程序的 Hello World。

内核中的程序 hello_kern.c:

代码语言:javascript代码运行次数:0运行复制

#include #include "bpf_helpers.h"#define SEC(NAME) __attribute__((section(NAME), used))SEC("tracepoint/syscalls/sys_enter_execve")int bpf_prog(void *ctx){    char msg[] = "Hello BPF from houmin!n";    bpf_trace_printk(msg, sizeof(msg));    return 0;}char _license[] SEC("license") = "GPL";

函数入口:

上述代码和普通的C语言编程有一些区别。

程序的入口通过编译器的 pragama __section(“tracepoint/syscalls/sys_enter_execve”) 指定的。入口的参数不再是 argc, argv, 它根据不同的 prog type 而有所差别。我们的例子中,prog type 是 BPF_PROG_TYPE_TRACEPOINT, 它的入口参数就是 void *ctx。

头文件:

代码语言:javascript代码运行次数:0运行复制

#include 

这个头文件的来源是kernel source header file 。它安装在 /usr/include/linux/bpf.h中。

它提供了bpf 编程需要的很多symbol。例如:

enum bpf_func_id 定义了所有的kerne helper function 的idenum bpf_prog_type 定义了内核支持的所有的prog 的类型。struct __sk_buff 是bpf 代码中访问内核struct sk_buff的接口。

等等

代码语言:javascript代码运行次数:0运行复制

#include “bpf_helpers.h”

来自libbpf ,需要自行安装。我们引用这个头文件是因为调用了bpf_printk()。这是一个kernel helper function。

程序解释:

这里我们简单解读下内核态的 ebpf 程序,非常简单:

bpf_trace_printk 是一个 eBPF helper 函数,用于打印信息到 trace_pipe (/sys/kernel/debug/tracing/trace_pipe),详见这里[5]代码声明了 SEC 宏,并且定义了 GPL 的 License,这是因为加载进内核的 eBPF 程序需要有 License 检查,类似于内核模块

加载 BPF 代码:

用户态程序 hello_user.c:

代码语言:javascript代码运行次数:0运行复制

#include #include "bpf_load.h"int main(int argc, char **argv){    if(load_bpf_file("hello_kern.o") != 0)    {        printf("The kernel didn't load BPF programn");        return -1;    }    read_trace_pipe();    return 0;}

在用户态 ebpf 程序中,解读如下:

通过 load_bpf_file 将编译出的内核态 ebpf 目标文件加载到内核通过 read_trace_pipe 从 trace_pipe 读取 trace 信息,打印到控制台中

修改 samples/bpf 目录下的 Makefile 文件,在对应的位置添加以下三行:

代码语言:javascript代码运行次数:0运行复制

hostprogs-y += hellohello-objs := bpf_load.o hello_user.oalways += hello_kern.o

重新编译,可以看到编译成功的文件:

代码语言:javascript代码运行次数:0运行复制

$ make M=samples/bpf$ ls -hl samples/bpf/hello*-rwxrwxr-x 1 ubuntu ubuntu 404K Mar 30 17:48 samples/bpf/hello-rw-rw-r-- 1 ubuntu ubuntu  317 Mar 30 17:47 samples/bpf/hello_kern.c-rw-rw-r-- 1 ubuntu ubuntu 3.8K Mar 30 17:48 samples/bpf/hello_kern.o-rw-rw-r-- 1 ubuntu ubuntu  246 Mar 30 17:47 samples/bpf/hello_user.c-rw-rw-r-- 1 ubuntu ubuntu 2.2K Mar 30 17:48 samples/bpf/hello_user.o

进入到对应的目录运行 hello 程序,可以看到输出结果如下:

代码语言:javascript代码运行次数:0运行复制

$ sudo ./hello           -102735 [001] ....  6733.481740: 0: Hello BPF from houmin!           -102736 [000] ....  6733.482884: 0: Hello BPF from houmin!           -102737 [002] ....  6733.483074: 0: Hello BPF from houmin!

代码解读

前面提到 load_bpf_file 函数将 LLVM 编译出来的 eBPF 字节码加载进内核,这到底是如何实现的呢?

经过搜查,可以看到 load_bpf_file 也是在 samples/bpf 目录下实现的,具体的参见 bpf_load.c[6]。

阅读 load_bpf_file 代码可以看到,它主要是解析 ELF 格式的 eBPF 字节码,然后调用 load_and_attach[7] 函数。

在 load_and_attach 函数中,我们可以看到其调用了 bpf_load_program 函数,这是 libbpf 提供的函数。

调用的 bpf_load_program 中的 license、kern_version 等参数来自于解析 eBPF ELF 文件,prog_type 来自于 bpf 代码里面 SEC 字段指定的类型。

代码语言:javascript代码运行次数:0运行复制

static int load_and_attach(const char *event, struct bpf_insn *prog, int size){  bool is_socket = strncmp(event, "socket", 6) == 0; bool is_kprobe = strncmp(event, "kprobe/", 7) == 0; bool is_kretprobe = strncmp(event, "kretprobe/", 10) == 0; bool is_tracepoint = strncmp(event, "tracepoint/", 11) == 0; bool is_raw_tracepoint = strncmp(event, "raw_tracepoint/", 15) == 0; bool is_xdp = strncmp(event, "xdp", 3) == 0; bool is_perf_event = strncmp(event, "perf_event", 10) == 0; bool is_cgroup_skb = strncmp(event, "cgroup/skb", 10) == 0; bool is_cgroup_sk = strncmp(event, "cgroup/sock", 11) == 0; bool is_sockops = strncmp(event, "sockops", 7) == 0; bool is_sk_skb = strncmp(event, "sk_skb", 6) == 0; bool is_sk_msg = strncmp(event, "sk_msg", 6) == 0;    //...   fd = bpf_load_program(prog_type, prog, insns_cnt, license, kern_version,         bpf_log_buf, BPF_LOG_BUF_SIZE); if (fd < 0) {  printf("bpf_load_program() err=%dn%s", errno, bpf_log_buf);  return -1; }  //...}

3

eBPF 特性

Hook Overview

eBPF 程序都是事件驱动的,它们会在内核或者应用程序经过某个确定的 Hook 点的时候运行,这些 Hook 点都是提前定义的,包括系统调用、函数进入/退出、内核 tracepoints、网络事件等。

Service Mesh架构新技能之eBPF入门与实践

如果针对某个特定需求的 Hook 点不存在,可以通过 kprobe 或者 uprobe 来在内核或者用户程序的几乎所有地方挂载 eBPF 程序。

Service Mesh架构新技能之eBPF入门与实践

Verification

With great power there must also come great responsibility.

每一个 eBPF 程序加载到内核都要经过 Verification,用来保证 eBPF 程序的安全性,主要包括:

要保证加载 eBPF 程序的进程有必要的特权级,除非节点开启了 unpriviledged 特性,只有特权级的程序才能够加载 eBPF 程序。

1、内核提供了一个配置项 /proc/sys/kernel/unprivileged_bpf_disabled 来禁止非特权用户使用 bpf(2) 系统调用,可以通过 sysctl 命令修改

2、比较特殊的一点是,这个配置项特意设计为一次性开关(one-time kill switch), 这意味着一旦将它设为 1,就没有办法再改为 0 了,除非重启内核

3、一旦设置为 1 之后,只有初始命名空间中有 CAP_SYS_ADMIN 特权的进程才可以调用 bpf(2) 系统调用 。Cilium 启动后也会将这个配置项设为 1:

代码语言:javascript代码运行次数:0运行复制

$ echo 1 > /proc/sys/kernel/unprivileged_bpf_disabled

要保证 eBPF 程序不会崩溃或者使得系统出故障。

要保证 eBPF 程序不能陷入死循环,能够 runs to completion。

要保证 eBPF 程序必须满足系统要求的大小,过大的 eBPF 程序不允许被加载进内核。

要保证 eBPF 程序的复杂度有限,Verifier 将会评估 eBPF 程序所有可能的执行路径,必须能够在有限时间内完成 eBPF 程序复杂度分析。

JIT Compilation

Just-In-Time(JIT)编译用来将通用的 eBPF 字节码翻译成与机器相关的指令集,从而极大加速 BPF 程序的执行:

与解释器相比,它们可以降低每个指令的开销。通常,指令可以 1:1 映射到底层架构的原生指令这也会减少生成的可执行镜像的大小,因此对 CPU 的指令缓存更友好特别地,对于 CISC 指令集(例如 x86),JIT 做了很多特殊优化,目的是为给定的指令产生可能的最短操作码,以降低程序翻译过程所需的空间

64 位的 x86_64、arm64、ppc64、s390x、mips64、sparc64 和 32 位的 arm 、x86_32 架构都内置了 in-kernel eBPF JIT 编译器,它们的功能都是一样的,可以用如下方式打开:

代码语言:javascript代码运行次数:0运行复制

$ echo 1 > /proc/sys/net/core/bpf_jit_enable

32 位的 mips、ppc 和 sparc 架构目前内置的是一个 cBPF JIT 编译器。这些只有 cBPF JIT 编译器的架构,以及那些甚至完全没有 BPF JIT 编译器的架构,需要通过内核中的解释器(in-kernel interpreter)执行 eBPF 程序。

要判断哪些平台支持 eBPF JIT,可以在内核源文件中 grep HAVE_EBPF_JIT:

代码语言:javascript代码运行次数:0运行复制

$ git grep HAVE_EBPF_JIT arch/arch/arm/Kconfig:       select HAVE_EBPF_JIT   if !CPU_ENDIAN_BE32arch/arm64/Kconfig:     select HAVE_EBPF_JITarch/powerpc/Kconfig:   select HAVE_EBPF_JIT   if PPC64arch/mips/Kconfig:      select HAVE_EBPF_JIT   if (64BIT && !CPU_MICROMIPS)arch/s390/Kconfig:      select HAVE_EBPF_JIT   if PACK_STACK && HAVE_MARCH_Z196_FEATURESarch/sparc/Kconfig:     select HAVE_EBPF_JIT   if SPARC64arch/x86/Kconfig:       select HAVE_EBPF_JIT   if X86_64
Service Mesh架构新技能之eBPF入门与实践

Maps

BPF Map 是驻留在内核空间中的高效 Key/Value store,包含多种类型的 Map,由内核实现其功能,具体实现可以参考我的这篇博文[8]。

Service Mesh架构新技能之eBPF入门与实践

BPF Map 的交互场景有以下几种:

BPF 程序和用户态程序的交互:BPF 程序运行完,得到的结果存储到 map 中,供用户态程序通过文件描述符访问BPF 程序和内核态程序的交互:和 BPF 程序以外的内核程序交互,也可以使用 map 作为中介BPF 程序间交互:如果 BPF 程序内部需要用全局变量来交互,但是由于安全原因 BPF 程序不允许访问全局变量,可以使用 map 来充当全局变量BPF Tail call:Tail call 是一个BPF程序跳转到另一BPF程序,BPF程序首先通过 BPF_MAP_TYPE_PROG_ARRAY 类型的 map 来知道另一个BPF程序的指针,然后调用 tail_call() 的 helper function 来执行Tail call

共享 map 的 BPF 程序不要求是相同的程序类型,例如 tracing 程序可以和网络程序共享 map,单个 BPF 程序目前最多可直接访问 64 个不同 map。

Service Mesh架构新技能之eBPF入门与实践

当前可用的通用 map 有:

BPF_MAP_TYPE_HASHBPF_MAP_TYPE_ARRAYBPF_MAP_TYPE_PERCPU_HASHBPF_MAP_TYPE_PERCPU_ARRAYBPF_MAP_TYPE_LRU_HASHBPF_MAP_TYPE_LRU_PERCPU_HASHBPF_MAP_TYPE_LPM_TRIE

以上就是Service Mesh架构新技能之eBPF入门与实践的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/33452.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
VSCode如何集成Neo4j图数据库工具 VSCode图形数据库管理插件配置方法
上一篇 2025年11月4日 10:39:45
极光影票如何设置观影提醒_极光影票电影开场提醒设置
下一篇 2025年11月4日 10:40:05

相关推荐

  • 蝴蝶号直播掉帧、断流怎么办?技术实用建议

    蝴蝶号直播掉帧、断流怎么办?技术实用建议蝴蝶号直播掉帧、断流怎么办?技术实用建议蝴蝶号直播掉帧、断流怎么办?技术实用建议蝴蝶号直播掉帧、断流怎么办?技术实用建议

    解决蝴蝶号直播掉帧、断流问题需从硬件、软件、网络三方面入手。1. 硬件方面:检查cpu和gpu压力,必要时升级硬件或降低分辨率、帧率;确保摄像头、采集卡、内存正常工作。2. 软件方面:调整分辨率、帧率、码率至合适水平;使用h.265或硬件编码减轻cpu负担;设置关键帧间隔为2秒;关闭后台程序并检查平…

    2026年9月21日 用户投稿
    300
  • 如何使用Ribbet的AI功能裁剪图片?快速实现精准图像裁剪

    答案:Ribbet的AI裁剪功能可快速智能识别主体并推荐裁剪方案,支持手动微调与多种比例选择,结合亮度、色彩等编辑工具优化效果,适用于制作符合社交媒体尺寸要求的封面图,操作简便且大部分功能免费,适合追求效率的普通用户。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepS…

    2026年9月21日
    400
  • SystemTap

    SystemTap 简介 systemtap 是一款用于诊断 linux 系统性能或功能问题的开源工具。它使得对运行中的 linux 系统进行诊断和调试变得更加便捷和高效。有了 systemtap,开发者和调试人员无需重新编译内核、安装新内核或重启系统等繁琐步骤。为了解决系统问题或提升性能,开发者只…

    2026年9月21日
    100
  • Xdebug性能优化:解决PHP调试器导致页面加载缓慢或超时的问题

    当Xdebug配置不当,即使未主动调试,也可能导致PHP应用页面加载缓慢或超时。本文将深入探讨Xdebug的工作原理,指导如何通过正确配置xdebug.mode、排查多配置文件冲突,并利用Xdebug日志进行诊断,从而有效解决调试器造成的性能瓶颈,确保开发环境的流畅运行。 理解Xdebug的连接机制…

    2026年9月21日
    000
  • 卢伟冰:功能手机、智能手机之后 手机行业正进入新周期

    9月4日,小米集团总裁卢伟冰表示,继功能机时代与智能机时代之后,全球手机产业正迈入一个全新时代。 卢伟冰今日在社交平台发文提到:“我从2002年进入手机行业,有幸完整见证了功能手机和智能手机两大发展阶段。如今,AI时代已经到来,整个行业正在酝酿深刻变革,步入全新的发展周期。” 回望过去,功能手机时期…

    2026年9月21日
    200
  • 谷歌浏览器官方主站入口 最新Chrome在线登录页面

    谷歌浏览器官方主站入口是https://www.google.com,该页面具备界面简洁、操作流畅、集成化服务入口和个性化推荐等特点,支持多设备访问且无广告干扰。 谷歌浏览器官方主站入口在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来谷歌浏览器最新Chrome在线登录页面相关信息,感兴趣的…

    2026年9月21日
    000
  • win11怎么退回win10系统_win11降级回win10系统操作教程

    可在10天内通过系统恢复功能退回Windows 10,保留文件但卸载新增应用;超期则需用媒体工具或第三方软件重装,后者操作更简便但会清除数据。 如果您最近将系统升级到 Windows 11,但发现使用不习惯或存在兼容性问题,则可以考虑退回至 Windows 10。在特定时间窗口内,Windows 提…

    2026年9月21日
    000
  • VSCode怎么设置变量窗口_VSCode调试时变量监视面板使用教程

    答案:配置launch.json并设置断点后,通过VSCode调试界面的变量和监视面板可实时查看变量值。具体包括正确设置program路径,利用变量面板查看作用域内变量,使用监视面板添加表达式或变量进行持续跟踪,结合调试按钮控制执行流程,并可通过条件断点、控制台输出、debugger语句、Sourc…

    2026年9月21日
    100
  • Java 正则表达式:查找双引号内所有指定字符串的出现次数

    本文旨在解决在 Java 中使用正则表达式查找双引号内特定字符串(例如 “variant”)的所有出现次数的问题。我们将提供一个完整的解决方案,包括正则表达式的构建、代码示例以及详细的解释,帮助开发者准确高效地完成此类任务。 在 Java 中,使用正则表达式查找字符串中特定模…

    2026年9月21日
    000
  • MySQL 大型历史数据表结构设计与优化指南

    本文旨在为处理大量客户历史交易数据的MySQL数据库设计提供专业指导。我们将探讨如何构建高效、可扩展的表结构,重点关注主键设计、数据分区、实时数据摄入以及性能优化策略,以确保系统能够稳定支持百万级乃至亿级数据量的查询需求。 MySQL大型历史数据表结构设计与优化 在处理大量历史数据,特别是涉及到多用…

    2026年9月21日
    000
  • MySQL重复数据检测与清理逻辑_Sublime脚本批量处理历史冗余记录

    MySQL重复数据检测与清理逻辑_Sublime脚本批量处理历史冗余记录MySQL重复数据检测与清理逻辑_Sublime脚本批量处理历史冗余记录MySQL重复数据检测与清理逻辑_Sublime脚本批量处理历史冗余记录MySQL重复数据检测与清理逻辑_Sublime脚本批量处理历史冗余记录

    处理mysql重复数据的核心步骤是识别并清理,可使用group by或窗口函数定位重复项,再通过分批删除或倒腾法安全清理;sublime text可用于高效生成和编辑sql语句。1. 识别重复数据常用group by+having或row_number()窗口函数;2. 清理策略包括分批删除、使用临…

    2026年9月21日 用户投稿
    100
  • 如何用PyTorch训练AI大模型?构建高效神经网络的完整教程

    如何用PyTorch训练AI大模型?构建高效神经网络的完整教程如何用PyTorch训练AI大模型?构建高效神经网络的完整教程如何用PyTorch训练AI大模型?构建高效神经网络的完整教程如何用PyTorch训练AI大模型?构建高效神经网络的完整教程

    PyTorch大模型训练需综合运用分布式训练、内存优化与高效计算策略。首先采用DistributedDataParallel实现多GPU并行,配合DistributedSampler确保数据均衡;通过混合精度训练、梯度累积和激活检查点缓解显存压力;使用torch.compile优化模型计算效率;选择…

    2026年9月21日 用户投稿
    100
  • vim 学习笔记(一)—— vim模式与创建、编辑文件

    vim 学习笔记(一)—— vim模式与创建、编辑文件vim 学习笔记(一)—— vim模式与创建、编辑文件vim 学习笔记(一)—— vim模式与创建、编辑文件vim 学习笔记(一)—— vim模式与创建、编辑文件

    vim 是基于linux开发的一款强大文本编辑器,源自vi并进行了扩展,具有跨平台和广泛工具支持的特性。据说,vim的高手能够以思想的速度在键盘上操作文本,因此我决定加入学习的行列。学习资料是b站上的生肉教程【公开课】完美的vim课程【生肉】,该教程侧重于讲解vim的思想和精髓,而非具体命令的详细介…

    2026年9月21日 用户投稿
    100
  • 360浏览器如何查看版本号 360浏览器查看当前版本信息方法

    1、通过帮助与反馈菜单可查看360浏览器版本,点击右上角菜单→帮助和反馈→关于360安全浏览器,即可显示完整版本号及更新状态。 如果您需要确认当前使用的360浏览器具体版本,以便进行功能核对或问题排查,可以通过浏览器内置的菜单选项快速获取该信息。 本文运行环境:联想小新Pro 16,Windows …

    2026年9月21日
    1000
  • QQ好友消息不提示怎么办 QQ消息通知设置与恢复方法

    手机QQ收不到消息提示通常因通知权限关闭或设置问题,需检查QQ内【新消息通知】开关是否开启;2. 查看手机系统设置中QQ的通知权限,确保允许显示通知并开启声音、震动等提醒;3. 使用QQ内置的【消息通知修复】工具自动修复异常;4. 关闭省电模式或将QQ加入电池优化白名单,确保后台正常运行。 手机QQ…

    2026年9月21日
    000
  • win10打开图片提示“没有注册类”怎么办_win10图片打开注册类错误解决方案

    首先重置照片应用并修复系统文件,再通过PowerShell重新注册应用包,最后调整默认应用关联以解决“没有注册类”错误。 如果您尝试在Windows 10中打开图片文件,但系统弹出“没有注册类”的错误提示,则可能是由于默认图片查看应用的注册信息丢失或损坏。以下是解决此问题的步骤: 本文运行环境:De…

    2026年9月21日
    200
  • Xdebug配置与故障排除:解决PHP调试连接导致的网页超时问题

    本文旨在解决Xdebug在IDE未监听调试连接时可能导致的网页加载缓慢或超时问题。我们将深入探讨Xdebug的工作原理、关键配置参数,并提供一套系统的故障排除方法,包括如何启用详细日志记录以及检查多重配置文件的影响,以确保Xdebug仅在需要时激活,避免不必要的性能开销。 1. 理解Xdebug的工…

    2026年9月21日
    100
  • 一部手机+蝴蝶号账号,开启你的直播副业之路

    一部手机+蝴蝶号账号,开启你的直播副业之路一部手机+蝴蝶号账号,开启你的直播副业之路一部手机+蝴蝶号账号,开启你的直播副业之路一部手机+蝴蝶号账号,开启你的直播副业之路

    开启直播副业确实可行,但需系统规划与长期坚持。1.选择舒适且有热情的内容领域,如技能教学、生活经验或兴趣分享,确保可持续输出;2.利用智能手机基础设备,搭配支架、补光灯等低成本工具提升画面稳定与光线效果;3.注册直播平台账号后,熟悉后台功能以优化直播体验;4.初期通过社交媒体预告宣传引流,并以高质量…

    2026年9月21日 用户投稿
    000
  • 怎么全选VSCode多个光标_VSCode多光标操作与批量选择文本教程

    VSCode中高效创建多光标的方法包括:Alt+Click手动添加光标,适用于不规则位置;Ctrl+Alt+方向键垂直添加光标,适合连续多行操作;Ctrl+D逐个选择匹配项,精准控制选择范围;Ctrl+Shift+L一次性选择所有匹配项,实现全局批量修改。结合查找替换和列选择模式可进一步提升编辑效率…

    2026年9月21日
    100
  • MySQL自动化性能测试方案_MySQL持续监控调优数据库效率

    MySQL自动化性能测试方案_MySQL持续监控调优数据库效率MySQL自动化性能测试方案_MySQL持续监控调优数据库效率MySQL自动化性能测试方案_MySQL持续监控调优数据库效率MySQL自动化性能测试方案_MySQL持续监控调优数据库效率

    mysql自动化性能测试和持续监控的核心在于构建闭环反馈系统,包含模拟真实负载、全面数据采集、自动化执行与分析、数据驱动的持续调优四大环节。①测试环境需与生产一致并隔离,使用docker、虚拟机或云沙盒,解决数据同步与脱敏问题;②负载生成工具如sysbench、jmeter、locust或自定义脚本…

    2026年9月21日 用户投稿
    200

发表回复

登录后才能评论
关注微信