利用 DeepFlow 为传统 APM 开启全栈追踪能力

DeepFlow开源
• 阅读 320

传统 APM 聚焦在代码层面,不具备全栈多维度无盲点看问题的能力,同时由于插码的阻碍往往难以覆盖所有微服务,DeepFlow 依靠 eBPF 零代码修改采集全栈追踪数据并聚合生成了调用关系,可以增强传统 APM 的数据,大大缩短问题定界时间。对于已经使用传统 APM 工具的用户,可以考虑使用 DeepFlow 提供的 API 来增强应用依赖拓扑及调用追踪,以获得全栈数据追踪能力。

本文以 SkyWalking 为例从落地实现角度来描述,如何将在传统 APM 中集成 DeepFlow 的数据,增强传统 APM 数据能力, 主要从以下两个角度来:

  • 依赖拓扑:增强查看某历史时间范围内服务(POD)到服务(POD)全栈路径拓扑以及全景上下游拓扑。
  • 调用链追踪:增强查看某个应用 Span 对应系统 Span、网络 Span 时延消耗以及追踪未插码服务的能力。

开启下文的阅读之前,需要对 DeepFlow 目前已有的数据及术语有了解,下文默认读者都有一定的认知。

01

全栈路径拓扑-界面

增强查看某历史时间范围内服务(POD)到服务(POD)应用和网络指标量能力,可以快速回答在某一段时间内端到端路径是否存在瓶颈点,下面将结合 Skywalking 介绍产品 UI 界面如何融合

第一步:聚焦需要查看的路径(以下举例通过拓扑图路径点击,大家可以根据环境的实际情况来定义使用流程)

利用 DeepFlow 为传统 APM 开启全栈追踪能力
聚焦需要查看的路径
利用 DeepFlow 为传统 APM 开启全栈追踪能力
点击全栈路径拓扑

第二步:查看全栈路径拓扑(增强能力)

利用 DeepFlow 为传统 APM 开启全栈追踪能力
查看全栈路径拓扑

上图拓扑中每一个节点都对应一个统计位置(tap_side),统计位置的说明参考 DeepFlow 官网的线上文档[1],以客户端容器节点举例说明具体的含义,表达是 cartservice 服务访问 redis-cart 服务,在 cartservice 对应 POD 所在的容器节点上采集到的访问数据,然后聚合的指标量。上图查看的指标量为响应时延,不难看出瓶颈在服务端容器网络,判断过程如下:

  • 客户端时延:④=204.31ms,为请求服务端的总时延,由以下几部分组成
    • 客户端容器网络:路径①(也就是⑤-④),图中所示为38.14us
    • 云网络:路径②(也就是⑥-⑤),图中所示为273.13us
    • 服务端容器网络:路径③(也就是⑦-⑥),图中所示为204.25ms
    • 服务端:即图中⑦,为372.83us

02

全栈路径拓扑-API

结合 API 看看如何实现,DeepFlow 的所有数据均可通过 SQL API 获取。

调用方输入客户端名称服务端名称指标量以及时间范围作为 API 的搜索条件即可获得全栈路径拓扑数据。

第一步:获取 Skywalking 路径的客户端服务及服务端名称,根据需求明确需要查看的指标量及查看的时间范围

利用 DeepFlow 为传统 APM 开启全栈追踪能力
Skywalking 输入

第二步:查询 DeepFlow 获取应用/网络统计位置的数据,SQL 调用参考 DeepFlow 官网的线上文档[2]

SELECT Avg(`request`), /* 需要查看的指标量 */ 
       pod_service_0,  /* 客户端服务名称,客户端为 POD,则替换为 pod_0 */
       tap_side, 
       pod_service_1 /* 服务端服务名称,服务端为 POD,则替换为 pod_1 */
FROM vtap_app_edge_port  /* 查看应用指标使用 vtap_app_edge_port;查看网络指标切换到 vtap_flow_edge_port */
WHERE time>=1678760220 AND time<=1678762020 AND 
      pod_service_0='deepflow-server' AND  /* 过滤客户端 */
      pod_service_1='deepflow-server'   /* 过滤服务端 */
GROUP BY pod_service_0, 
         tap_side, 
         pod_service_1,

第三步:根据返回数据绘制拓扑图

每个 tap_side 对应一个节点,节点根据 c-app/app/c-p/c/c-nd/c-hv/c-gw-hv/c-gw/local/rest/s-gw/s-gw-hv/s-hv/s-nd/s/s-p/s-app 从左到右排序,每个节点独立显示指标数据

03

全景上下游拓扑-界面

增强某节点查看全景上下游拓扑的能力,可快速发现未插码范围内被谁访问了(比如追踪上游的 Nginx 网关、安全策略未防住的访问等等),以及自身访问了谁,下面也将结合 Skywalking 介绍产品 UI 界面如何融合

第一步:聚焦需要查看的节点(以下举例通过拓扑图节点点击,大家可以根据环境的实际情况来定义使用流程)

利用 DeepFlow 为传统 APM 开启全栈追踪能力
点击全景上下游拓扑

第二步:查看全景上下游拓扑(增强能力)

利用 DeepFlow 为传统 APM 开启全栈追踪能力
查看全景上下游拓扑

上图为 tikcet-web 服务的全景上下游拓扑,其中 ① 是未插码的 ingress-nginx-controller 服务,表明 ticket-web 服务对外都是通过 ingress 来访问的,其中 ② 为未插码的 kube-dns 服务,经常访问服务慢,可能是因为 DNS 解析慢,而在应用拓扑是无法看出来此信息的。

04

全景上下游拓扑-API

调用方输入服务名称指标量以及时间范围作为 API 的搜索条件即可获得全景上下游拓扑数据,需要两次调用的 DeepFlow API,分别获取到上游和下游的数据如下:

获取上游数据

SELECT Avg(`request`), /* 需要查看的指标量 */ 
       pod_service_0,  /* 客户端服务名称,客户端为 POD,则替换为 pod_0 */
       tap_side, 
       pod_service_1 /* 服务端服务名称,服务端为 POD,则替换为 pod_1 */
FROM vtap_app_edge_port  /* 查看应用指标使用 vtap_app_edge_port;查看网络指标切换到 vtap_flow_edge_port */
WHERE time>=1678760220 AND time<=1678762020 AND 
      pod_service_1='deepflow-server'   /* 需要查看上游数据的服务 */
GROUP BY pod_service_0, 
         tap_side, 
         pod_service_1,

获取下游数据

SELECT Avg(`request`), /* 需要查看的指标量 */ 
       pod_service_0,  /* 客户端服务名称,客户端为 POD,则替换为 pod_0 */
       tap_side, 
       pod_service_1 /* 服务端服务名称,服务端为 POD,则替换为 pod_1 */
FROM vtap_app_edge_port  /* 查看应用指标使用 vtap_app_edge_port;查看网络指标切换到 vtap_flow_edge_port */
WHERE time>=1678760220 AND time<=1678762020 AND 
      pod_service_0='deepflow-server'   /* 需要查看下游数据的服务 */
GROUP BY pod_service_0, 
         tap_side, 
         pod_service_1,

05

调用链追踪-产品

在开始介绍如何增强调用追踪的数据之前,先结合一张图说明一些后续要使用到的术语

利用 DeepFlow 为传统 APM 开启全栈追踪能力
数据介绍图
  • 图中 A 表示应用 Span(来源传统 APM);S 表示网络 Span(来源 DeepFlow);N 表示网络 Span(来源 DeepFlow)
  • 图中黑色部分为发起全栈调用追踪的的应用 Span,后续统称为 应用 Span Y
  • 图中蓝色部分为通过 应用 Span Y 追踪的路径中的系统和网络 Span
  • 图中绿色部分为通过 应用 Span Y 追踪的下游未插码的 Span
  • 图中红色部分为通过 应用 Span Y 追踪的上游未插码的 Span

接下来将分别来讨论上图中蓝色/绿色/红色部分如何基于 SkyWalking 产品做 UI 融合(注:以下产品 UI 部分仅为示意图):

第一步:聚焦需要查看的应用 Span(以下举例通过点击 Span,大家可以根据环境的实际情况来定义使用流程)

利用 DeepFlow 为传统 APM 开启全栈追踪能力
聚焦需要查看的路径
利用 DeepFlow 为传统 APM 开启全栈追踪能力
点击全栈调用追踪

第二步:查看全栈调用拓扑(增强能力)

利用 DeepFlow 为传统 APM 开启全栈追踪能力
查看全栈调用拓扑

06

调用链追踪-API

接下来看下结合 DeepFlow 的 SQL API 如何实现,基于前面的术语介绍图,可知传统 APM 结合 DeepFlow 的数据来完成全栈调用追踪的能力,需要分蓝色、绿色和红色三部分来实现,接下来将分开介绍这三部分的数据实现。

蓝色部分:根据 应用 Span 的 TraceID + SpanID 追踪 DeepFlow 的系统 Span 和网络 Span,可以方便的查看某次调用在系统和网络分布消耗的时延,快速定界问题。可以通过 TraceID、SpanID 作为搜索条件获取 DeepFlow 的系统和网络 Span

利用 DeepFlow 为传统 APM 开启全栈追踪能力
蓝色部分-追踪图
SELECT response_duration,
       start_time,
       end_time,
       resource_gl0_0, /* 客户端 */
       resource_gl0_1, /* 服务端 */
       tap_port_type,  /* eBPF、NIC ... */
       tap_port,       /* NIC Name */
       trace_id,
       span_id
FROM l7_flow_log
WHERE trace_id = 'c5ad367da7ed41fc97921d91a0584bd8.63.16620935428909473' AND
      span_id = 'e05ee7a06d674085a16dfea36ed11b98.169.16620935428971714-2' AND /* 非必须,精确搜索 */
      time >= 1662093572 AND time <= 1662095372 /* 加速搜索 */

此部分的细节部分可以参考DeepFlow 让 SkyWalking 分布式追踪无盲点[3]

红色部分:增强某个应用 Span 上游的 Span,对于插码范围以外(之前)的部分,例如追踪出来从未插码的客户端 Span

利用 DeepFlow 为传统 APM 开启全栈追踪能力
红色部分-追踪原理解释图

对于这部分数据的追踪,需要分几个步骤来逐一进行关联

  • ① 根据应用 Span Y 的 TraceID + SpanID 追踪 DeepFlow 的系统 Span,此时可能会得到多个系统 Span,只需要获取与应用 Span Y紧邻的系统 Span X继续往下追踪即可(可通过总时延最长来判断)
  • ② 获取系统 Span X的 syscall_trace_id_request 作为其他系统 Span 的搜索条件,得到系统 Span Z
SELECT response_duration,  /* SELECT 字段可以根据需求自定义即可*/
       l7_protocol,
       Enum(request_type),
       request_resource,
       process_kname_0,
       process_kname_1,
       tap_side,
       req_tcp_seq, 
       resp_tcp_seq,
       Enum(auto_instance_type_0) AS `client_Enum(auto_instance_type_0)`,
       auto_instance_0,  
       Enum(auto_instance_type_1) AS `server_Enum(auto_instance_type_1)`, 
       auto_instance_1, 
FROM l7_flow_log  
WHERE time>=1678764261 AND /*追踪开始时间,建议设置比系统 Span X 的开始时间早 3min*/
      time<=1678767861 AND /*追踪结束时间,建议设置比系统 Span X 的结束时间晚 3min*//
      (syscall_trace_id_request=16787489195430278) /* 16787489195430278 为 系统 Span Y 的 syscall_trace_id_request */
ORDER BY `end_time` 

  • ③ 获取系统 Span Z 的 req_tcp_seq/resp_tcp_seq 作为其他系统 Span 和网络 Span 的搜索条件,得到网络 Span Z.1/Z.2 以及系统 Span Q,此处逻辑特别注意:req_tcp_seq !=0 & resp_tcp_seq !=0 则需要同时满足 req_tcp_seq 和 resp_tcp_seq;如果其中一个为 0,则任意满足一个即可
SELECT response_duration,  /* SELECT 字段可以根据需求自定义即可*/
       l7_protocol,
       Enum(request_type),
       request_resource,
       process_kname_0,
       process_kname_1,
       tap_side,
       req_tcp_seq, 
       resp_tcp_seq,
       Enum(auto_instance_type_0) AS `client_Enum(auto_instance_type_0)`,
       auto_instance_0,  
       Enum(auto_instance_type_1) AS `server_Enum(auto_instance_type_1)`, 
       auto_instance_1, 
FROM l7_flow_log  
WHERE time>=1678764261 AND 
      time<=1678767861 AND 
      (type=2 AND 
      req_tcp_seq=3575241005 AND /* 3575241005 为系统 Span Z 的 req_tcp_seq*/
      resp_tcp_seq=995863176) /* 995863176 为系统 Span Z 的 resp_tcp_seq*/
ORDER BY `end_time` 
  • ④ 接下来可继续追踪系统 Span Q 的上游系统 Span,这里将分两种情况,如果上游的系统 Span 与系统 Span Q 在同一个线程,则重复步骤 [2]/[3] 即可,如果在不同线程/进程中,目前仅支持网关设置了 X-Request-ID 的情况下继续追踪,获取系统 Span Q的 x-request-id 作为查询其他系统 Span 和网络 Span 的搜索条件,得到其上游的系统 Span M
SELECT response_duration,  /* SELECT 字段可以根据需求自定义即可*/
       l7_protocol,
       Enum(request_type),
       request_resource,
       process_kname_0,
       process_kname_1,
       tap_side,
       req_tcp_seq, 
       resp_tcp_seq,
       Enum(auto_instance_type_0) AS `client_Enum(auto_instance_type_0)`,
       auto_instance_0,  
       Enum(auto_instance_type_1) AS `server_Enum(auto_instance_type_1)`, 
       auto_instance_1, 
FROM l7_flow_log  
WHERE time>=1678764261 AND 
      time<=1678767861 AND 
      x_request_id=6e903947-5ef0-4c63-91a8-a2a599171633 /* 6e903947-5ef0-4c63-91a8-a2a599171633 为系统 Span Q 的 x_request_id*/
ORDER BY `end_time` 
  • ⑤ 到此,已经根据上述步骤追踪得到所有的上游 Span,接下来将确定父子关系,可直接根据总的响应时延,按从大到小降序排列即可

绿色部分:增强某个应用 Span 下游的 Span,对于插码范围以外(之后)的部分追踪,例如追踪出来未插码的服务端 Span(DNS),此追踪过程与红色部分非常相似,仅步骤 ② 中的syscall_trace_id_request换成syscall_trace_id_response即可,此处不在赘述。

利用 DeepFlow 为传统 APM 开启全栈追踪能力
绿色部分-追踪图

07

什么是 DeepFlow

DeepFlow[4] 是一款开源的高度自动化的可观测性平台,是为云原生应用开发者建设可观测性能力而量身打造的全栈、全链路、高性能数据引擎。DeepFlow 使用 eBPF、WASM、OpenTelemetry 等新技术,创新的实现了 AutoTracing、AutoMetrics、AutoTagging、SmartEncoding 等核心机制,帮助开发者提升埋点插码的自动化水平,降低可观测性平台的运维复杂度。利用 DeepFlow 的可编程能力和开放接口,开发者可以快速将其融入到自己的可观测性技术栈中。

GitHub 地址:https://github.com/deepflowys/deepflow

访问 DeepFlow Demo[5],体验高度自动化的可观测性新时代。

参考资料

[1]

统计位置的说明参考 DeepFlow 官网的线上文档: https://deepflow.io/docs/zh/auto-metrics/metrics-without-instrumentation/

[2]

SQL 调用参考 DeepFlow 官网的线上文档: https://deepflow.io/docs/zh/server-integration/query/sql/

[3]

DeepFlow 让 SkyWalking 分布式追踪无盲点: https://deepflow.io/blog/007-skywalking-distributed-tracing-without-blind-spots/#0x1-DeepFlow-SQL-API

[4]

DeepFlow: https://github.com/deepflowys/deepflow

[5]

DeepFlow Demo: https://deepflow.yunshan.net/docs/zh/install/overview/

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Stella981 Stella981
3年前
JVM 字节码指令表
字节码助记符指令含义0x00nop什么都不做0x01aconst\_null将null推送至栈顶0x02iconst\_m1将int型1推送至栈顶0x03iconst\_0将int型0推送至栈顶0x04iconst\_1将int型1推送至栈顶0x05ic
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
DeepFlow开源
DeepFlow开源
Lv1
技术创造价值
文章
3
粉丝
3
获赞
3