应用监控 eBPF 版:实现高效协议解析的技术探索

2024-01-24 07:20

本文主要是介绍应用监控 eBPF 版:实现高效协议解析的技术探索,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者:彦鸿

引言

随着 Kuberentes 等云原生技术的飞速发展,带来了研发与运维模式的变革。企业软件架构由单体服务向分布式、微服务演进。随着业务发展,多语言、多框架、多协议的微服务在企业中越来越多,软件架构复杂度越来越高,如何快速通过可观测工具快速定位出问题对研发人员至关重要。为满足全场景、端到端的应用监控需求,应用实时监控服务 ARMS 推出应用监控 eBPF 版,通过 eBPF 技术完善整个应用监控体系。应用监控 eBPF 版提供无侵入、语言无关的可观测能力。

详细产品介绍: 多语言应用监控最优选,ARMS 应用监控 eBPF 版正式发布

使用 eBPF 来进行可观测性需要进行应用层协议解析,但云上微服务软件架构中的应用层协议往往比较复杂,这也给协议解析带来了不小的挑战。传统的协议解析方式存在 CPU、内存占用高,错误率高等问题,在应用监控 eBPF 版中,我们提出一种高效的协议解析方案,实现对应用层协议的高效解析。

eBPF 技术简介

eBPF(扩展的 Berkeley 包过滤器)是一种强大的技术,允许开发人员在 Linux 内核中安全地运行预编译的程序,而不改变内核源码或加载外部模块 [ 1] 。这一独特的能力使得 eBPF 成为构建现代、灵活且高效的应用监控工具的理想选择。

图片

图 2.1 eBPF 示意图

在可观测性方面,eBPF 优势尤为突出:

  • 实时性: eBPF 能够实时捕获和分析数据,为开发者提供即时的性能反馈。
  • 精确性: 通过精细的 hook 函数(hook points),eBPF 可以在系统的具体点进行监控,从而准确地收集所需数据。
  • 灵活性: 开发者可以编写定制的 eBPF 程序来监控特定事件,使其能够适应各种复杂的监控需求。
  • 低开销: eBPF 程序直接在内核空间运行,避免了传统监控工具中频繁的用户空间和内核空间之间的上下文切换。
  • 安全性: eBPF 程序在执行前必须通过内核的严格检查,确保不会危及系统安全。

传统的协议解析方案

图片

图 3.1 传统协议解析方案架构图

3.1 传统方案的解析流程

基于 eBPF 来做数据抓取和协议解析的传统方案主要分为:

  • 数据采集
  • 数据传递
  • 协议解析

其中数据采集主要在内核态,数据传递介于内核态和用户态,协议解析在用户态进行。具体的,数据采集的流程为 eBPF 使用 kprobe 或 tracepoint 方式,从内核中抓取到流量事件即 event,这些事件中有控制层面的事件如从 connect、close 等系统调用处采集到的事件。也有数据层面的事件,如从 read、write 等系统调用处采集到的事件。待数据采集到内核事件后,我们需要将数据从内核态传递至用户态去做进一步的处理。在 eBPF 中,我们采用 perf buffer(一种特殊 eBPF Map)来做数据传递。数据存放到整个 perf buffer 后,在用户态进行协议解析。

3.2 传统方案中存在的问题

传统的解析方案中 CPU、内存占用过高,在高流量场景下错误率较高,主要体现在以下三个方面:

  • 高内存占用: 数据采集中无法筛选协议,导致大量无关数据占满 perf buffer,引发内存过高。
  • 事件丢失风险: 高 QPS 导致 perf buffer 迅速填满,处理不及时会丢失事件,特别是控制层事件可能因数据层事件过多而丢失。
  • 解析效率低: 需要遍历尝试所有支持协议才能找到正确的协议,导致大量无效解析,增加 CPU 负担。

实现高效协议解析的技术探索

4.1 高效的协议解析方案流程

鉴于上文所述传统方案中存在的问题,本文提出一种高效的协议解析方案,本文所述方案主要分为四部分:

  • 数据采集
  • 协议推断
  • 事件分流
  • 协议解析

其中协议解析由分为:

  • 连接维护
  • 数据分帧
  • 协议解析
  • 请求-响应匹配

图片

图 4.2 本文所述协议解析框架图

如图 4.2 所示,eBPF 首先在内核态中采集到数据,根据协议帧头进行协议推断。根据协议推断的结果,可以初步判断改数据帧是否是所支持的协议。如果判断为“是”,才传递至用户态进行进一步解析,否则不进行处理。进行简单的事件过滤后,本文根据事件的类型进行事件分流。

如控制事件放到 control events perf buffer 中,数据事件放到 data event perf buffer。事件传递至用户态后控制事件将用于连接维护,数据事件根据其数据流向,分别放入发送队列和接收队列中。然后周期性的从对队列中的数据进行分帧处理,这样可以很好的解决单发多收、多发单收、多发多收等场景。从接受队列或发送队列(也可以理解为数据流)中拆解出单独的帧数据后将会通过按照内核态中推断的协议类型去匹配对应的协议解析器进行进一步解析。分别解析出请求与响应后,需要去匹配请求和响应,完成一个完成的可观测记录,即 record,后续也将通过 record 来生成可观测中的 Span。

本章后续小节将会重点讲解图 4.2 中的关键流程,即协议推断器(protocol infer)、协议解析进行详解。

4.2 协议推断(protocol infer)

顾名思义,协议推断主要用于在采集到数据包时,通过协议的协议帧头来推测是否是支持的协议类型。如果是支持的类型则将数据传递至用户态进行进一步处理。

以 MySQL5.7 协议为例:在 MySQL5.7 协议中,如果第一帧数据为 MySQL 的命令帧,如图 4.3 所示,命令帧有以下几种类型,具体见 MySQL 官方文档协议 [ 2]

图片

图 4.3 MySQL 命令帧

但在这里,具体是不是真的是 MySQL 协议还到用户态解析时进一步确认。基于此,我们在内核中先通过简单的判读进行推断,简易的推断代码如下:

static __inline enum protocol_type_t infer_mysql(const char* buf, size_t count) {static const uint8_t query = 0x03;static const uint8_t connect = 0x0b;static const uint8_t stmtPrepare = 0x16;static const uint8_t stmtExecute = 0x17;static const uint8_t stmtClose = 0x19;if (buf[0] == connect || buf[0] == query || buf[0] == stmtPrepare || buf[0] == stmtExecute ||buf[0] == stmtClose) {return request;}return unknown;
}

4.3 协议解析(conn tracker)

整个协议解析流程主要是在 conn tracker 组件中进行,其主要的能力有:

  • 连接维护
  • 数据分帧
  • 协议解析
  • 请求-响应匹配

具体的,在长连接场景下每次数据传输的基本元数据信息,如 source ip、 source port、dest ip、dest port 等信息总是相同的。如图 4.4 所示,如果我们能够在用户态维护其连接信息,那这部分连接相关的元数据信息就不必每次都放入 perf buffer 中,只用传递连接 ID 即可,进一步降低网络带宽。

图片

图 4.4 conn tracker 连接维护图

其次有部分协议,如 MySQL 协议,有部分 MySQL 相关信息,如版本号,编码等信息只在初次建立连接时候会发送包信息,如果用户态没有维护连接信息,则这部分元数据信息将无法解析。

上文提到的内核中采集到的数据会放置接收队列、发送队列两个队列中,也可以理解为数据流。从整个数据流中分解出每一帧的数据是进行协议解析的前提。基本思路是根据每种协议的结束帧标识来做判断,如 MySQL 响应的 EOF 帧信息。图 4.5 所示为 MySQL 协议分帧示意图。

图片

图 4.5  MySQL 协议分帧示意图

分解出每一帧的数据后,就按照各个协议进行协议解析即可。

图片

图 4.6 MySQL 协议解析示意图

在可观测中,我们需要有一个完整的请求-响应记录。以 MySQL 协议为例,由于 MySQL 协议是按照时间序有序的,请求的时间序和响应的时间序能进行对应,响应总是以 EOF 结束,EOF 帧为以下形式。

图片

图 4.7 MySQL Response 结束帧(EOF)

参考 MySQL 官方文档 [ 2]

图片

图 4.8 MySQL 请求-响应匹配示意图

总结

基于 eBPF 因其高性能,低开销,无侵入等特点近年来成为可观测性的研究热点。基于 eBPF 来进行应用监控必须进行协议解析。当前传统的协议解析方案存在 CPU、内存开销大,错误率高等问题。基于此本文提出一种高效的协议解析框架,并在阿里云应用实时监控服务 ARMS  “应用监控 eBPF 版” [ 1] 中正式发布。成功接入后将会出现如下的应用监控展示大盘,以下是展示示意图。

使用的测试项目 github 地址:alibabacloud-microservice-demo [ 3]

图片

图 5.1 应用监控 eBPF 版-概览

图片

图 5.2 应用监控 eBPF 版-数据库分析

图片

图 5.2 应用监控 eBPF 版-应用拓扑

具体接入流程见下方链接,仅需一分钟即可无死角监控您的应用。详细情况可进钉钉群(群号:35568145)进行交流。

目前,应用监控 eBPF 版处于免费使用阶段,并于近期将会推出网络监控、数据库分析、CPU Profiling [ 1] 等能力。欢迎开发者体验与使用。点击阅读原文,立即体验。

参考链接:

[1] 多语言应用监控最优选,ARMS 应用监控 eBPF 版正式发布

[2] https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_com_init_db.html

[3] https://github.com/aliyun/alibabacloud-microservice-demo

这篇关于应用监控 eBPF 版:实现高效协议解析的技术探索的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/638928

相关文章

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

使用IDEA部署Docker应用指南分享

《使用IDEA部署Docker应用指南分享》本文介绍了使用IDEA部署Docker应用的四步流程:创建Dockerfile、配置IDEADocker连接、设置运行调试环境、构建运行镜像,并强调需准备本... 目录一、创建 dockerfile 配置文件二、配置 IDEA 的 Docker 连接三、配置 Do

全面解析Golang 中的 Gorilla CORS 中间件正确用法

《全面解析Golang中的GorillaCORS中间件正确用法》Golang中使用gorilla/mux路由器配合rs/cors中间件库可以优雅地解决这个问题,然而,很多人刚开始使用时会遇到配... 目录如何让 golang 中的 Gorilla CORS 中间件正确工作一、基础依赖二、错误用法(很多人一开

深入浅出SpringBoot WebSocket构建实时应用全面指南

《深入浅出SpringBootWebSocket构建实时应用全面指南》WebSocket是一种在单个TCP连接上进行全双工通信的协议,这篇文章主要为大家详细介绍了SpringBoot如何集成WebS... 目录前言为什么需要 WebSocketWebSocket 是什么Spring Boot 如何简化 We

Java Stream流之GroupBy的用法及应用场景

《JavaStream流之GroupBy的用法及应用场景》本教程将详细介绍如何在Java中使用Stream流的groupby方法,包括基本用法和一些常见的实际应用场景,感兴趣的朋友一起看看吧... 目录Java Stream流之GroupBy的用法1. 前言2. 基础概念什么是 GroupBy?Stream

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统