0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

什么是DeepFlow?DeepFlow的协议能力解析

Linux阅码场 来源:Linux阅码场 2023-11-03 12:31 次阅读

1

简介

DeepFlow 利用 eBPF 采集并解析应用协议,实现了零侵扰的分布式追踪和指标数据的采集。DeepFlow 已经内置支持了十多种应用协议的解析,并且还在持续增加中。但我们发现实际业务环境中情况会更加复杂:开发会坚持返回 HTTP 200 同时将错误信息放到自定义 JSON 结构中,大量 RPC 的 Payload 部分使用 Protobuf、Thrift 等依赖 Schema 进行解码的序列化方式,调用的处理流程中发生了跨线程导致 eBPF AutoTracing 断链。

针对这些复杂场景,DeepFlow 实现了一套零侵扰的 WebAssembly 插件机制,使得开发人员可针对自己的业务环境定制化 DeepFlow 的协议解析能力。本文将分享两个案例,来介绍 DeepFlow 中的 Wasm 插件能力。

02

案例 - 解析 JSON 中的错误信息

在本例中,被监控 HTTP API 的响应消息为 JSON 格式,当 API 出错时 HTTP 协议的状态码可能仍然是 200,确切的错误信息通过 JSON 中的 OPT_STATUS 等字段返回

{
"OPT_STATUS":"AUTH_HEADER_ERROR",//不等于SUCCESS时表示调用失败
"DESCRIPTION":"请传递正确的验证头信息",//详细错误信息
...//其他返回字段
}

查阅 API 文档后我们得知,OPT_STATUS的值不等于SUCCESS时表示 API 调用失败。在常规的 DeepFlow 解析流程中,会按照如下方式构造 HTTP 调用日志的各个字段:

response_code:赋值为 HTTP 响应头中的状态码,例如 200、404、500 等

response_status:状态码小于 400 时认为正常,4XX 认为是客户端异常,5XX 认为是服务端异常

response_exception:赋值为 HTTP 异常状态码对应的英文解释,例如 404 时此字段赋值为 Not Found

response_result:当 HTTP 状态码为异常时赋值为整个 HTTP Payload

当我们安装了 Wasm 插件后,我们可以在上述解析的基础上,将失败 API 的调用日志中的如下字段进行覆写,以实现正确体现业务错误的效果:

response_code:当 JSON 中 OPT_STATUS != SUCCESS、且 HTTP 状态码小于 400 时,此值覆写为 500

response_status:按照新的 response_code 重新赋值,例如 500 时赋值为服务端异常

response_exception:当 JSON 中的 OPT_STATUS != SUCCESS时覆写为 DESCRIPTION 字段的值

response_result:当 response_code 大于等于 400 时赋值为整个 JSON Payload

我们将 Wasm 插件代码放到了这个 GitHub 仓库[1]中。上述 API 行为描述的实际上是 DeepFlow 企业版中的 statistics 服务,下面演示将此 Wasm 插件注入到 DeepFlow Agent 以后,对 DeepFlow 企业版服务的自我观测效果。首先我们在命令行中触发一次 statistics 服务的 API 调用:

#请求
curlhttps://cloud.deepflow.yunshan.net/api/statistics/v1/stats/querier/DBDescription/ShowDatabases

#HTTP响应头
HTTP/2401
date:Tue,22Aug20230129GMT
content-type:application/json
content-length:152

#HTTP响应体
{
"DATA":false,
"DESCRIPTION":"请传递正确的验证头信息",
"ERR":null,
"LEVEL":0,
"OPT_STATUS":"AUTH_HEADER_ERROR"
}

上述 API 响应中,HTTP 的状态码为 401,OPT_STATUS=AUTH_HEADER_ERROR。我们能在 DeepFlow 页面正确的看到客户端异常指标:

9f17bc16-79f3-11ee-939d-92fbcf53809c.jpg

01-client_error_metrics

在 DeepFlow 调用日志页面,可以看到客户端异常的调用日志的详情信息,整个 JSON body 放在了response_result里面:

9f3c0c24-79f3-11ee-939d-92fbcf53809c.jpg

02-request_log

对该调用发起追踪,能看到是因为fauths返回的 401 异常:

9f4410f4-79f3-11ee-939d-92fbcf53809c.jpg

03-tracing

下面是详细的调用链。第一步发起 DNS 请求:

9f6b3f76-79f3-11ee-939d-92fbcf53809c.jpg

04-dns

第二步调用后端服务验证 License:

9f897842-79f3-11ee-939d-92fbcf53809c.jpg

05-license

第三步发起 DNS 请求 fauths 服务的地址:

9faadd34-79f3-11ee-939d-92fbcf53809c.jpg

06-dns

第四步调用 fauth 的 /auth API 验证权限,中间需要访问 Redis 获取用户信息:

9fce63d0-79f3-11ee-939d-92fbcf53809c.jpg

07-fauth

9fd89a80-79f3-11ee-939d-92fbcf53809c.jpg

08-redis

03

案例 - 提取流水号并用于分布式追踪

在金融行业的核心交易系统中,服务之间通常通过在 RPC 中传递一个流水号来实现分布式追踪。本例中我们编写了一个演示 Demo 服务,它演示了一个简单的 gRPC 客户端和服务端。我们知道 gRPC 的消息体是使用 Protobuf 序列化的,本例将演示如何利用 DeepFlow 的 Wasm 插件机制解析这个 Demo 中的 Protobuf 消息,获取其中的流水号,并最终实现分布式追踪。Wasm 插件的代码可以在这个 GitHub 仓库[2]中找到。

本例中的 gRPC 消息定义如下:

serviceGame{
rpcGame(OrderRequest)returns(OrderResponse);
}

messageOrderRequest{
stringbusiness_id=1235;
}

messageOrderResponse{
stringmsg=1235;
}

在 Wasm 插件中,我们将 gRPC Payload 中的 business_id 字段的值赋值到 trace_id 中,用于分布式调用链追踪。同时会将 business_id 及 msg 等原始字段在调用日志的 Native tag 中存储一份,分别对应 attribute.business_id 及 attribute.msg,可用于业务查看更详细的交易信息。

我们将 gRPC Demo 部署在 cloud.deepflow 环境中 Sandbox K8s 集群里,安装好 Wasm 插件后,在 DeepFlow 页面直接过滤 l7_protocol = Custom 即可看到这个私有协议的指标和调用日志数据:

a00188f0-79f3-11ee-939d-92fbcf53809c.png

08-metrics

a0280fde-79f3-11ee-939d-92fbcf53809c.png

09-request-log

a0554e86-79f3-11ee-939d-92fbcf53809c.png

10-tracing

04

如何使用 Golang SDK 开发插件

Wasm 插件可使用多种语言开发,目前 DeepFlow 对 Golang 提供了一个 SDK,开发可以参考文档[3]。其中核心的步骤如下:

新建一个 go 项目, 并且拉取 Golang SDK

gomodinitProjectName&&gogetgithub.com/deepflowio/deepflow-wasm-go-sdk

在插件中实现协议解析逻辑

packagemain

import(
"github.com/deepflowio/deepflow-wasm-go-sdk/sdk"
)

funcmain(){
sdk.Warn("pluginloaded")
sdk.SetParser(SomeParser{})
}

typeSomeParserstruct{
}

func(pSomeParser)HookIn()[]sdk.HookBitmap{
return[]sdk.HookBitmap{
//一般只需要hook协议解析
sdk.HOOK_POINT_PAYLOAD_PARSE,
}
}

func(pdnsParser)OnHttpReq(ctx*sdk.HttpReqCtx)sdk.HttpAction{
returnsdk.ActionNext()
}

func(pdnsParser)OnHttpResp(ctx*sdk.HttpRespCtx)sdk.HttpAction{
returnsdk.ActionNext()
}

func(pdnsParser)OnCheckPayload(ctx*sdk.ParseCtx)(uint8,string){
//这里是协议判断的逻辑,返回0表示失败
//return0,""
return1,"someprotocol"
}

func(pdnsParser)OnParsePayload(ctx*sdk.ParseCtx)sdk.ParseAction{
//这里是解析协议的逻辑
ifctx.L4!=sdk.TCP||ctx.L7!=1{
returnsdk.ActionNext()
}
returnsdk.ActionNext()
}

编译为 Wasm 插件

tinygobuild-owasm.wasm-targetwasi-panic=trap-scheduler=none-no-debug*.go

05

如何在 DeepFlow 中部署插件

将编译好的插件上传至 deepflow-server

deepflow-ctlplugincreate--typewasm--imagewasm.wasm--namewasm-demo-1

修改 deepflow-agent 的组配置,添加需要加载的插件

static_config:
ebpf:
#对于deepflow-agent原生不支持的协议,eBPF数据需要添加端口白名单才能上报
kprobe-whitelist:
port-list:9999

#如果配置了l7-protocol-enabled,别忘了放行Custom类型的协议
l7-protocol-enabled:
-Custom
#otherprotocol

wasm-plugins:
-wasm-demo-1//对应deepflow-ctl上传插件的名称

注:目前修改此配置后 deepflow-agent 会自动重启。

检查插件是否正确加载

kubectl-ndeepflowlogs-fdeepflow-agent-xxxxx|grep-iplugin

a076f6bc-79f3-11ee-939d-92fbcf53809c.png

11-check

我们看到插件 main 函数里的 warn 日志正常输出,说明插件加载成功了。

06

总结

DeepFlow Wasm 插件机制提供了一个可编程的、安全的、资源消耗可控的运行沙箱,它是整个 DeepFlow Pipeline 机制的重要一环。它的使用场景包括:

增强原生支持的协议:在原生协议的解析能力基础之上,提取更多的业务信息

支持私有协议的解析:特别是从 Protobuf、Thrift 等依赖 Schema 的 Payload 内容中提取业务字段

零侵扰分布式追踪:通过解析调用中的事务全局 ID,用于实现分布式追踪

自定义脱敏:对 MySQL、Redis 等协议中的业务敏感信息进行抹除

未来,我们还会基于 Wasm 插件提供更强大的可编程性。例如:

自定义过滤:对调用日志进行基于 URL、Endpoint 等字段的过滤

自定义采样:通过对 TraceID 等追踪字段的分析,决定是否对调用日志进行采样丢弃

07

什么是 DeepFlow

DeepFlow[4] 开源项目旨在为复杂的云原生应用提供深度可观测性。DeepFlow 基于 eBPF 实现了零插桩(Zero Code)、全覆盖(Full Stack)的指标、追踪、日志采集,并通过智能标签技术实现了所有观测数据的全关联(Universal Tagging)和高效存取。使用 DeepFlow,可以让云原生应用自动具有深度可观测性,从而消除开发者不断插桩的沉重负担,并为 DevOps/SRE 团队提供从代码到基础设施的监控及诊断能力。

编辑:黄飞

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • API
    API
    +关注

    关注

    2

    文章

    1383

    浏览量

    60994
  • HTTP
    +关注

    关注

    0

    文章

    467

    浏览量

    30316
  • 服务端
    +关注

    关注

    0

    文章

    62

    浏览量

    6871
  • JSON
    +关注

    关注

    0

    文章

    111

    浏览量

    6819

原文标题:什么是 DeepFlow

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    RS-232-C串口通讯协议解析

    RS-232-C串口通讯协议解析
    发表于 08-18 22:08

    CANOpen协议解析

    CANOpen协议解析
    发表于 08-20 17:26

    知道通讯协议,怎么用LabVIEW解析

    知道通讯协议,求大师指导怎么用LabVIEW解析
    发表于 05-06 20:19

    解析协议的方法有哪几种?

    解析协议的方法有哪几种?
    发表于 12-02 06:49

    PS/2接口协议解析及应用

     PS/2接口协议解析及应用
    发表于 07-03 14:29 1989次阅读

    地址解析协议ARP

    地址解析协议ARP 地址解析协议 ARP 是一种广播协议,主机通过它可以动态地
    发表于 06-09 21:53 1037次阅读
    地址<b class='flag-5'>解析</b><b class='flag-5'>协议</b>ARP

    地址解析协议(ARP),地址解析协议(ARP)是什么意思

    地址解析协议(ARP),地址解析协议(ARP)是什么意思 地址解析协议 (ARP) “地址
    发表于 04-06 09:07 1983次阅读

    基于KMP算法的串口通讯协议解析邹铁

    基于KMP算法的串口通讯协议解析_邹铁
    发表于 03-17 08:00 2次下载

    西门子PPI协议解析资料下载

    ppi协议解析
    发表于 03-23 10:03 46次下载

    TCP IP协议:地址解析协议ARP

    TCP IP协议进级讲座:2,地址解析协议
    的头像 发表于 07-03 06:05 3546次阅读

    汽车常用ISO15765协议解析

    汽车常用ISO15765协议解析说明。
    发表于 06-02 10:04 31次下载

    协议解析网关的作用

    想要了解协议解析网关,我们不妨将这个词拆来来看,协议+解析+网关三者的组合就是协议解析网关,三者
    的头像 发表于 09-09 11:18 1098次阅读

    DeepFlow AutoTagging 10x性能提升实战

    我们认为应用开发团队花了一半的时间用于可观测性的建设。这张图里面可以看到,开发者通常需要考虑在不同的 Dev Stack 和 Infra Stack 中如何埋点、如何插码、如何传递追踪上下文、如何生成指标/追踪/日志数据并进行关联,需要考虑的问题太多太杂。
    的头像 发表于 02-16 11:01 441次阅读

    DeepFlow在小米落地现状以及挑战

    我还补充一下,目前小米和 DeepFlow 合作的方式是以社区共建的形式合作的,我们这边也投入人力,然后在社区中走的都是社区的正规流程,提 FR、PR,然后我本人也提供过多个 FR 和多个 PR。
    的头像 发表于 06-29 16:12 331次阅读
    <b class='flag-5'>DeepFlow</b>在小米落地现状以及挑战

    如何构建APISIX基于DeepFlow的统一可观测性能力呢?

    随着应用组件的可观测性逐渐受到重视,Apache APISIX 引入插件机制丰富了可观测数据源。
    的头像 发表于 01-18 10:11 393次阅读
    如何构建APISIX基于<b class='flag-5'>DeepFlow</b>的统一可观测性<b class='flag-5'>能力</b>呢?