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

基于eBPF的交易系统可观测技术

原创 夏克 2024-01-02
649

作者  夏克

摘 要:eBPF(Extended Berkeley Packet Filter)技术是最近10年linux内核最热门也是最具影响力的技术之一,随着网络和云原生技术的飞速发展,eBPF被广泛的应用于网络和安全、性能分析、容器和云原生、运维和排障以及对应用系统的观测。本文将针对如何使用eBPF技术对交易系统运行状态、处理能力和性能热点观测进行实践。eBPF技术的引入会在交易系统的开发、测试、运维阶段极大提高效率并降低成本,对性能优化,辅助测试以及生产运维期间的故障定位和排查提供有效的手段。

一、引言

交易系统是证券期货交易所关键基础设施之一,为保障其稳定、高效运行,在开发、测试、运维等方面提出了更高的要求,对调试手段、测试工具、运维监控等环节的前沿技术引入也更加迫切。近几年,随着信息技术应用创新工作的逐步落地,国产操作系统将逐步应用于交易所应用系统的生产环境,国产操作系统的内核版本相对目前生产操作系统的Redhat/CentOS7.x(v3.10)有了明显的提升,目前主流的国产操作系统,如麒麟、统信等,其内核版本为v4.19(或更高)。内核版本的提升为eBPF技术的引入提供了先决条件。eBPF技术的引入将极大程度的解决上述环节面临的痛点和问题。下文将简要介绍eBPF的相关技术,并对定位性能瓶颈、辅助测试和增强运维几个方面展开说明eBPF技术在交易系统中的应用。

二、eBPF技术

1、eBPF发展史

仅仅数年,eBPF已一跃成为了现代基础设施领域中最热门的技术之一,早期的BPF(Berkeley Packet Filter)在1992年由Steven McCanne和Van Jacobson提出,用于过滤网络数据包。BPF提供了一种在内核中执行简单过滤器程序的方法,以实现高效的数据包过滤和捕获。BPF在1997年被引入到Linux内核中,成为Linux内核中的一项功能。它通过允许用户在内核空间中运行自定义的BPF程序,扩展了内核的功能。eBPF最初在2014年引入到Linux内核中,它是对传统BPF的扩展和增强。eBPF引入了虚拟机,提供了更强大的功能和更灵活的执行环境,使得用户能够在内核中运行更复杂的代码,从而极大程度的扩展了BPF技术的使用范围。

2、eBPF工作原理

eBPF工作原理如图1所示,首先用户编写eBPF内核代码(kernel),并使用编译器(clang -target bpf)将内核跟踪代码编译成BPF字节码(BPF bytecode),通过系统调用(Syscall bpf())或BCC、bpftool等工具将字节码加载到内核,验证器(verifier)会对加载的字节码进行校验,校验通过后,当探针(probes)被触发时,eBPF跟踪函数则会在内核空间被执行,同时在内核空间可以开辟一块映射区(maps),用于内核空间与用户空间的数据交换,用户空间应用可以通过maps拿到内核跟踪代码搜集到的相关信息进行统计、分析和展示。

图1、eBPF工作原理

3、eBPF工具链

随着eBPF技术的不断发展,大量的配套工具和开源项目应运而生,不仅在Linux内核中融入了libbpf,同时在各种使用场景中也有着相当丰富的工具,包括基础工具、开发工具、网络/云原生工具、观测跟踪工具等等,如表1所示:

表1 eBPF工具

应用领域

开源项目/工具

观测跟踪

skydrive、hubble、weave scope、kubectl-trace、pwru、DeepFlow、pixie、eCapture、inspektor-gadget

网络/云原生

cilium、calico、katran、Tracee、policube、falco、kubeArmor、Tetragon、DeepFlow

开发库

bcc、libbpf、gobpf、libbpf-rs、Redbpf、ebpf(go)

基础工具

LLVM/Clang、GCC、bpftool、bpftrace、bcc

以BCC工具集为例,eBPF可以观测几乎所有内核函数和系统调用,如图2所示:

图2、BCC工具集

4、eBPF探针

eBPF主要有四种探针类型,分别可以以动态和静态的形式探测内核指令和用户应用:

  1. 内核探针:内核探针几乎可以在任何内核指令上设置动态标记或中断,并且系统损耗最少。内核探针分为两种:kprobes和kretprobes。
    1. kprobes:允许在执行内核指令之前插入BPF程序。
    2. kretprobes:是在内核指令有返回值是插入BPF程序。
  2. 跟踪点(tracepoint):是一种静态内核探针,跟踪点与kprobes的主要区别在于跟踪点由内核开发人员在内核中编写静态代码而埋下的探针,由于静态探针更加安全,因此推荐尽可能使用跟踪点。
  3. 用户空间探针:用户空间探针允许在用户空间运行的程序中设置动态标记,探针包括两种:uprobes和uretprobes。
    1. uprobes:是内核在用户控件程序特定指令执行前插入该指令集的钩子。
    2. uretprobes:与kretprobes类似,适用于用户空间程序使用,它将BPF程序附加到指令返回值上,允许通过BPF代码从寄存器中访问返回值。
  4. 用户静态定义跟踪点(USDT):是用户空间的应用在编码阶段静态写入的跟踪点,是检查应用程序的便捷方法。

图3展示了bpftrace工具对应用和内核各模块的探针类型。

IMG_256

图3、bpftrace探针类型

三、eBPF在交易系统中的应用

eBPF已在Linux系统内核中得到了广泛引用,在Kylin v10 sp3(内核版本4.19)系统上,内核探针就有51572个,几乎可以观测任何系统调用和内核模块。结合交易系统,本章将以具体的实践案例,如图4(棕色背景框)展示如何使用eBPF在交易系统开发、测试和运维等各环节中使用。

注:理论上可以在交易系统任何函数上进行观测,本文只介绍一些典型的场景。

图4 eBPF在交易系统中的probes

1、性能瓶颈定位

交易系统在排查性能问题时经常使用perf工具,而perf工具自Linux4.4内核版本开始支持使用eBPF作为性能分析工具的一种机制,强大的perf工具结合火焰图可以帮助定位性能热点,是性能优化过程中的利器。然而,虽然perf的功能足够强大,但作为通用的工具其灵活性和使用范围受到了一定的限制,为了补充perf工具的功能eBPF提供可定制的性能瓶颈定位手段。用户可以根据自己的需求和被观测系统的特点进行定制开发性能观测工具,同时eBPF的很多框架也提供了非常全面的工具集,如BCC提供了从应用程序、系统调用、文件系统、网络协议等大量的观测工具。下面将介绍基于一些BCC提供的eBPF工具对交易系统性能的观测方法。

1)查看读写文件情况(file_top)

IMG_256

图5 file_top

2)查看磁盘IO状态(bio_top)

图6 bio_top

3)查看缓存命中率(cache_hit)

IMG_258

图7 cache_hit

2、辅助测试

1)随机丢包测试(package_filter)

在非功能测试时,一些场景构建相对复杂,比如测试TCP/UDP的丢包场景来模拟网络环境不佳,使用eBPF可以比较方便的实现这个场景。实现原理如图8,XDP BPF程序可以在网络包进入内核协议栈时将其捕获并对其进行Drop,实现模拟丢包的场景。

descript

图8 XDP Drop Package

BPF内核部分代码片段如图9,其中if(...)可根据具体的过滤条件(如IP,端口等)对网络数据包进行过滤。

descript

图9 BPF内核底阿妈片段

# 编译

clang -O2 -target bpf -c xdp_drop_random.c -o xdp_drop_random.o

# 加载

ip link set dev eth0 xdp obj xdp_drop_random.o

2)更细粒度的延时、吞吐测试

在交易系统的常规性能测试场景中一般包括全系统处理的延时和吞吐测试,比如订单处理延时、订单/成交峰值吞吐率等一些大粒度的测试场景,虽然也有像交易/行情网关负载这种模块级粒度的测试,整体上覆盖了交易系统的生产场景,但对于相对粒度更小的白盒性能测试,在做白盒性能测试时往往场景构造和性能数据的采集比较复杂,一些情况下需要自行开发测试工具并在代码中注入采集信息的日志,然而使用eBPF中的uprobe和uretprobe配合就可以获取进出函数的时间点,其差值就是该函数的运行时间。使用usdt可以更精确的获取两个采集点间的执行时间。如图10所示:

descript

图10 用户空间函数观测

  1. 内存泄漏检测(memleak/mallocstacks

对于内存泄漏检查常用的工具有gdb和Valgrind Memcheck等,虽然这两款工具在一些情况下可以有效的检测出内存泄漏问题,但他们也都有明显的缺点。gdb是最常用的调试工具,可用于定位内存泄漏的原因,但需要中断程序运行。Valgrind Memcheck需要将被检测的应用作为其子进程运行,并替代默认的 malloc/free 等分配函数,应用的运行速度会下降20倍以上。显然对于在线动态检查内存泄漏的场景是不适合的。对于内存泄漏的检测实际上就是判断申请(malloc)的堆内存是否被回收(free),实际就是观测内存分配器(glibc、jemalloc、tcmalloc等)的行为。BCC项目提供了两款非常实用的内存泄漏检测工具(memleak、mallocstacks)可以通过uprobe实现对应用内存分配和回收的在线观测,从而定位内存泄漏问题,如图11所示:

descript

图11 memleak观测内存泄漏

3、增强运维监控

1)日志增强(trace_vm)

为保障运维期间能够全面展示交易系统的运行状态、处理能力和性能数据,在开发阶段尽可能预设了各种级别的日志,虽然足够详细的日志可以最大限度的展示交易系统状态,也能在排障时快速定位问题,但不得不承认运行日志是把双刃剑,过多的日志数据将会严重影响交易系统的运行性能。如果在运行过程中需要调整日志进行问题排查,则需要重启系统修改配置文件。而eBPF作为一种内核注入式的观测技术,具备了热插拔的能力,可以使用eBPF的uprobes和usdt技术来实现日志热插拔——即只有在观测时开启,系统正常运行时性能不会受到影响。下面以一个下线的vm层统计报文处理时长的日志为例,使用bpftrace的uprobes探测点实现类似的功能,代码片段如图12。

descript

图12 uprobe代码片段

2)系统信息采集(trace_match)

图13是一个简单的通过usdt探针采集撮合核心状态的过程,使用用户定义探针在进入撮合核心算法时埋入(probe)探测点,这里使用bpftrace工具观测交易指令进入撮合核心的时间、统计一段时间内核心算法处理各类交易指令的类型和个数。

descript

图13 撮合状态观测

4、应用监控扩展

eBPF观测信息可通过agent进行采集,同时可以使用一些开源工具实现观测信息可视化,如ebpf_exporter可以结合Prometheus和Grafana显示I/O延迟情况,如图14所示。

descript

图14 ebpf_exporter演示

  1. 结论

随着信息技术应用创新的逐步落地,搭载更高内核版本的国产操作系统在交易所应用系统中得到广泛使用,使得一些前沿技术与交易系统的结合有了更多的可能性。eBPF技术的引入对交易系的开发、测试、运维等环节开拓了新思路。本文简要介绍了eBPF的相关技术,以及使用现有和定制开发的eBPF工具在交易系统各场景中的应用案例。当然,eBPF的应用领域并不限于此,eBPF已在云原生、容器、网络安全、全链路观测等诸多前沿技术领域上展露头角,相信很快就会看到eBPF在金融领域核心系统中得到更多的应用。

参考文献

[1] David Calavera,Lorenzo Fontana.Linux内核观测技术BPF.范彬,狄卫华,译.机械工业出版社,2020:57-70

[2] eBPF Documentation.https://ebpf.io/what-is-ebpf/

[3] BPF Compiler Collecton(BCC).https://github.com/iovisor/bcc

[4] bpftrace.https://github.com/iovisor/bpftrace

[5] ebpf_exporter.https://github.com/cloudflare/ebpf_exporter

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

评论