DeepFlow 基于 eBPF 实现了零插桩(Zero Code)的云原生利用可观测性,可能在不改代码、不改启动参数、不重启过程的前提下实现分布式追踪。这是一种全新的技术手段,因而不少用户在选型和落地 DeepFlow 的过程中会对它的性能开销存在疑难。到底 Agent 的运行会对业务造成什么样的影响?而 Agent 本身的资源开销又如何?这些问题咱们在 SIGCOMM 2023 论文《Network-Centric Distributed Tracing with DeepFlow: Troubleshooting Your Microservices in Zero Code》中都有体系化的答复,论文将于九月份正式公开。在此之前,为了尽快帮忙大家扫清落地 eBPF 可观测性的最初阻碍,最近咱们也将 DeepFlow Agent 的自动化测试后果放到了线上 Demo 页面中,本文将联合 Agent Daily Build 的测试数据,系统性的论述咱们的测试方法和测试后果,揭示 Agent 的业务影响和资源开销,帮忙大家扫清落地 eBPF 可观测性的最初阻碍。
通过剖析 Agent 的解决流程,咱们设计了 六个场景 进行全方位的评测。
测试结果表明 Agent 对典型高负载生产业务的 TPS 无任何影响、CPU 增长仅 0.46%、均匀单个调用的 RT 增长小于 1ms。Agent 对 HTTP 流量的解决性能不低于 Nginx,通过 eBPF uprobe 采集 Golang 协程信息的性能为 Pixie 计划的 2.5 倍。Agent 在 1 核 1GB 内存限度下可采集 90K RPS HTTP 流量,或 122K CPS 并发的 TCP 流量,或 20+Gbps(未到极限)TCP Flood 流量,或 1.28Mpps UDP Flood 流量。
具体的测试方法和测试数据见注释,具体的总结见文末章节。
Agent 解决流程
为了确定性能测试的办法,咱们首先须要对 Agent 的解决流程有肯定理解,做到对症下药。如下图所示,Agent 次要从三个 eBPF 接口获取数据,自下而上顺次是:
- 通过 AF_PACKET 联合 BPF 过滤程序,获取利用的网络包数据,用于采集 NET Span
- 通过 kprobe 和 tracepoint 接口,获取利用的零碎调用数据,用于采集 SYS Span,以及每个调用生命周期内的慢文件 IO 事件
- 通过 uprobe 接口,获取应用程序的函数调用数据,用于实现 Golang 等协程语言的零插桩分布式追踪,也用于采集 HTTP2/HTTPS 协定的 SYS Span
(DeepFlow Agent 解决流程)
当获取到 Packet/Socket/Function 数据之后,DeepFlow Agent 须要解析数据中的利用协定,获取 Span,并关联、聚合造成 Trace、Metrics、Logs 数据。特地的,对于 Packet 数据,Agent 还须要基于包聚合生成 TCP/UDP Flow,用于生成流日志,并计算网络层的吞吐、时延、异样等性能指标。
了解 Agent 解决流程当前,咱们心愿设计一组测试例,通过他们咱们心愿能评估:
-
Agent 的运行对业务性能有什么样的影响?
- 业务的 TPS(Transactions Per Second)升高了多少?
- 业务的 RT(Response Time)升高了多少?
- 业务的 CPU/MEM 耗费升高了多少?
-
Agent 本身的解决性能如何?
- 特定压力下 Agent 的 CPU/MEM 耗费如何?
- Agent 采集利用数据的 RPS 能力如何?
- Agent 采集网络数据的 CPS/BPS/PPS 能力如何?
测试方法和目标
首先,为了评估 Agent 对业务性能的影响,咱们心愿设计典型的业务场景来进行评估,并心愿能笼罩到 Agent 解决流程中的所有重要环节。咱们一共设计了三个场景,如下图所示:
(通过典型业务场景评估 Agent 对业务性能的影响)
场景 A – 典型云原生微服务:
DeepFlow 面向云原生场景,咱们首先找到了 Istio Bookinfo Demo。Istio 是一种风行的服务网格解决方案,在 GitHub 上领有 32.9K Star。这个 Demo 的利用拓扑见上图,咱们能够看到它由 Python、Java、Ruby、Node.JS 实现的四个微服务组成,每个微服务所在的 Pod 中运行着 Envoy 代理。这个 Demo 中的一个事务对应着拜访 4 个微服务的 4 个调用。特地值得咱们关注的是,因为 Envoy 的存在理论调用链深度会被拉长两倍。
场景 B – 极高性能极简业务:
除了惯例业务微服务以外,DeepFlow 还能采集并追踪基础设施服务。因而咱们打算测试一个极致高性能、极简业务逻辑的中间件服务。咱们抉择了 Nginx,咱们晓得它以性能强悍著称,它用 C 语言实现,而且咱们在测试中让他只是简略的回复一个默认动态页。咱们置信这个 Nginx Demo 本身的性能体现远超过任何一个理论的生产环境,咱们心愿应用这个 Demo 来阐明 DeepFlow Agent 的采集对极其高性能的中间件影响如何。
场景 C – 用 uprobe 追踪 Golang:
咱们晓得 eBPF 中 uprobe 的性能要显著低于 kprobe/tracepoint,Brendan Gregg 在他的著述《BPF 之巅 – 洞悉 Linux 零碎和利用性能》中给出的参考数据中 uprobe 开销大概为 tracepoint 的 14-20 倍。尽管 DeepFlow 中大量的 Probe 都在应用最高性能的 tracepoint,并辅以 kprobe,但咱们还是心愿能有一个场景专一于对 uprobe 性能影响的评估,看看理论业务场景下 DeepFlow Agent 的体现。因而咱们编写了一个 Golang Service 的 Demo,它对外提供一个 API,并会在 API 实现逻辑中调用上游的 Redis、MySQL、Nginx 三个服务。DeepFlow Agent 应用 uprobe 来 Hook Golang 服务的 runtime.execute 函数调用,用以跟踪协程的创立,因而这个服务每次响应 API 的 4 个调用都会触发一次 Hook。
所有上述三个场景,咱们均会别离测试停用 deepflow-agent(基线)、运行 deepflow-agent 两种状况,通过比照得出 Agent 对业务性能的影响。另外,咱们也会注入不同 TPS 的压力,直至达到业务极限解决能力,以评估不同压力下的影响是否存在差别。
另一方面,对于 Agent 本身解决性能 的评估,咱们会记录场景 A-C 中 deepflow-agent 过程的 CPU/MEM 开销。除此之外,咱们也心愿设计一些更极其的场景,用来评估 Agent 在资源受限状况下的 RPS/CPS/BPS/PPS 极限解决能力。
(评估 Agent 本身的解决性能)
场景 B – 压测 RPS:咱们复用了 Nginx Demo,向他注入极限 RPS 压力,并评估 Agent 在耗费一个逻辑核的场景下能解决多大 RPS 的 HTTP 流量。
场景 D – 压测 CPS:咱们编写了一个高并发 Flow 的流量生成器。这个生成器会在 tcp_client 和 tcp_server 两个过程之间构建超过 100K CPS 的沉闷并发连贯,用以压测 Agent 中的 flow_map 模块,结构高内存压力。
场景 E – 压测 BPS:咱们应用 iperf3 结构超过 20Gbps 的大流量,用以评估 Agent 对大吞吐流量的解决性能。
场景 F – 压测 PPS:咱们编写了一个 UDP Flood 流量生成器。这个生成器会从 udp_flood 过程收回超过 1Mpps 的流量,用以压测 Agent 对高频 Packet Data 的解决性能。
上述四个场景,咱们均会注入最高的压力,使得 Agent 的 CPU/MEM 之一达到 1C/1GB 的高水位。
接下来,咱们将会对所有上述六个场景的测试方法和后果进行具体的论述,测试过程中 DeepFlow Agent 全副应用默认配置,没有进行任何调优。自动化测试流程每天都会执行本文介绍的测试例,并将测试后果与 Git Branch、CommitID 关联,以帮忙开发者评估新性能对 Agent 的性能影响。
Agent 对业务的影响
(不同业务场景下 Agent 采集的 Span 数量)
场景 A – 典型云原生微服务 Istio Bookinfo:咱们应用 wrk2 来注入稳固的 TPS 负载,wrk2 会间接申请 Productpage 服务。所有的服务(包含 wrk2)部署在一个 8C16GB 的 K8s 节点上(CentOS 7、Kernel 4.19),咱们在该节点上部署 deepflow-agent Daemonset 来对所有调用进行采集,测试过程中限度了 deepflow-agent 资源耗费为 1C768MB。
基线场景下咱们为 Bookinfo 注入了耗费 整机 52.61% CPU(相当于 4.2 个逻辑核)的高负载申请,能够看到这是一个十分忙碌的业务场景,为了达到该负载咱们甚至特意减少了其中两个瓶颈服务的正本数:将 Productpage 调整为 4 正本、将 Details 调整为 2 正本。在这样的高负载下:
- 运行 deepflow-agent 前后,TPS 没有任何影响,均为 300/s
- 运行 deepflow-agent 前后,CPU 仅有 0.46% 的增长,简直感知不到,能够认为是统计误差
-
P50/P90 RT 别离有约 10ms 的增长,增长比例约为 12%
- 对于每个事务,DeepFlow 采集了 37 个 Span,因而 300 TPS 负载下的 Span 采集速率为 11,100/s
- 每个事务包含 26 个 SYS Span(eBPF)和 11 个 NET Span(cBPF)
- 每个事物共采集了 13 个 Server-side SYS Span,因而 均匀每个调用仅引入了 0.8ms 的 RT 增长
DeepFlow 通过 eBPF 采集这些 Span,基于翻新的关联算法实现了零插桩的分布式追踪,Span 之间的关联信息也是由 Agent 实时计算失去的:
(DeepFlow 零插桩分布式追踪 – Istio Bookinfo)
该场景下的局部测试数据如下(更多测试数据请查看 DeepFlow 在线 Demo 中的 Grafana Dashboard):
TPS | Bookinfo CPU | P50 RT | P90 RT | |
---|---|---|---|---|
无 Agent | 300 | 52.61% | 69.76ms | 87.81ms |
有 Agent | 300 | 52.85% | 80.06ms | 98.56ms |
变动幅度 | 0 | + 0.24% | + 10.30ms | + 10.75ms |
变动比例 | 0 | + 0.46% | + 14.76% | + 12.24% |
场景 B – 极高性能极简业务 Nginx:咱们仍然应用 wrk2 来注入稳固的 TPS 负载,wrk2 会间接申请 Nginx 提供的 Default Page 服务。为了缩小其余业务的烦扰,咱们将 Nginx 和 wrk2 部署在两个独自的虚拟机上(8C16GB、CentOS 7、Kernel 4.19),将 Nginx 的 worker 数量固定为 1 个。咱们在 Nginx 所在虚拟机上部署了 deepflow-agent,测试过程中限度了 deepflow-agent 资源耗费为 1C768MB。
基线场景下咱们为 Nginx 注入了 耗费单核 56.50% CPU 的高负载申请,能够看到这是一个十分忙碌的业务场景。在这样的极其高性能和高负载下:
- 运行 deepflow-agent 前后,TPS 没有任何影响,均为 40,000/s
-
运行 deepflow-agent 前后,Nginx CPU 增长了 26.60%,另外 deepflow-agent 耗费了 86.17% CPU
- 每次调用,deepflow-agent 会采集两个 Span,即 Span 采集速率为 80,000/s
- 这意味着 deepflow-agent 解决两倍调用耗费的 CPU = 86.17+26.6 = 112.77 = 2 倍 Nginx 基线状态下的 CPU 耗费
- 也就是说,deepflow-agent 的解决性能与 Nginx 雷同
- P50/P90 RT 别离仅有 0.13ms/0.22ms 的增长,增长比例约为 12%
该场景下的局部测试数据如下(更多测试数据请查看 DeepFlow 在线 Demo 中的 Grafana Dashboard):
TPS | Nginx CPU | P50 RT | P90 RT | Agent CPU | |
---|---|---|---|---|---|
无 Agent | 40,000 | 56.50% | 1.02ms | 1.68ms | — |
有 Agent | 40,000 | 83.10% | 1.15ms | 1.90ms | 86.17% |
变动幅度 | 0 | + 26.60% | + 0.13ms | + 0.22ms | — |
变动比例 | 0 | + 47.08% | + 12.75% | + 13.10% | — |
上述测试后果是在 Agent 默认配置下测得的。实际上因为 Agent 在全栈门路上不同地位采集到的 Span 中 request_domain、request_resource、response_result 等字段不会有变动,因而咱们能够开启 Agent 的浅层解析采集模式,针对 HTTP 流量仅解析首行判断协定类型和响应码。所有调用日志均开启浅层解析后,Agent 的性能体现为:
- 对 Nginx P50/P90 RT 的影响升高到 7.27%
-
deepflow-agent 本身 CPU 耗费升高到 66.5%
- 采集 80K RPS HTTP 数据耗费 66.5%,加上 Nginx CPU 增长的 25.50% CPU,总耗费为 92%
- 即 DeepFlow Agent 浅层解析时的解决能力为 Nginx 基线能力的 1.2 倍
浅层解析时的局部测试数据如下:
TPS | Nginx CPU | P50 RT | P90 RT | Agent CPU | |
---|---|---|---|---|---|
有 Agent(浅层解析) | 40,000 | 82.00% | 1.10ms | 1.80ms | 66.5% |
变动幅度 | 0 | + 25.50% | + 0.08ms | + 0.12ms | — |
变动比例 | 0 | + 45.13% | + 7.27% | + 7.27% | — |
场景 C – 用 uprobe 追踪 Golang:咱们应用 wrk2 来注入稳固的 TPS 负载,wrk2 会间接申请 go-server 提供的服务。咱们将 wrk2 和所有服务部署在一个虚拟机上(8C16GB、CentOS 7、Kernel 4.19),除了 wrk2 以外所有服务均应用 docker-compose 部署在 container 中。同样这台虚拟机上也部署了 deepflow-agent。测试过程中限度了 deepflow-agent 资源耗费为 1C768MB。
DeepFlow 中通过 eBPF uprobe 跟踪 Golang 协程的创立来实现零插桩的分布式追踪。为了无差别的让 uprobe 笼罩到每一个调用(HTTP、MySQL、Redis),本 Demo 中咱们没有注入 HTTP2/HTTPS 流量。
基线场景下咱们为 go-server 注入了 耗费单核 35.22% CPU 的申请负载。在这样的负载下:
-
运行 deepflow-agent 前后,TPS 没有任何影响,均为 140/s
- 每个事务采集了 15 个 Span,因而 140 TPS 负载下的 Span 采集速率为 2100/s
-
相比其余场景,运行 deepflow-agent 后 CPU 和 RT 增长略大
- 运行 deepflow-agent 前后,业务 CPU 增长了 9.58%,增长比例为 27.20%
- 运行 deepflow-agent 前后,业务 P50/P90 RT 别离有约 0.6ms 的增长,增长比例约为 17%
咱们看到 uprobe 的性能开销的确要略高于前两个场景(仅应用了 tracepoint/kprobe/AF_PACKET)。实际上每一次 uprobe Hook 触发会引起两次用户态和内核态间的上下文切换,每个事务中咱们 Hook 的 golang 函数触发了 4 次,因而会导致每个事务中减少 8 次上下文切换。
但值得提到的是,DeepFlow Hook 的 Golang 函数是通过三思而行的。咱们应用 runtime.execute 来跟踪协程和线程之间的关系,这是咱们目前能找到的性能影响最低的途经。作为比照 Pixie Hook 了 runtime.casgstatus 函数(未用于分布式追踪,仅用来获取协程 ID),它的调用频率会显著高于 runtime.execute。在比照测试中咱们发现,如果应用 Pixie 的计划,在以后场景下将会造成业务服务高达 67% 的 CPU 增长、高达 45% 的 RT 增长,对业务的影响是 DeepFlow 的 2.5 倍。
该场景下的局部测试数据如下(更多测试数据请查看 DeepFlow 在线 Demo 中的 Grafana Dashboard):
TPS | Nginx CPU | P50 RT | P90 RT | |
---|---|---|---|---|
无 Agent | 140 | 35.22% | 3.56ms | 3.95ms |
有 Agent | 140 | 44.80% | 4.18ms | 4.60ms |
变动幅度 | 0 | + 9.58% | + 0.62ms | + 0.65ms |
变动比例 | 0 | + 27.20% | + 17.42% | + 16.46% |
测试过程中咱们也对业务的内存开销进行了监控,但未察看到任何影响,思考到 DeepFlow 从原理上来讲不会减少业务过程的内存开销,因而咱们没有出现内存耗费数据。
Agent 本身解决性能
在前一个章节的场景 A-C 中,咱们同时也记录了 Agent 在高负载下的资源耗费,见下表(其中场景 A 的 CPU 耗费为整机百分比,共 8 核,其余场景为单核百分比):
场景 | 业务 TPS | 业务基线 CPU | Span 采集速率 | Agent CPU | Agent 内存 |
---|---|---|---|---|---|
A – Istio | 300 | 52.61% | 11,100 | 3.40% | 46.76 MB |
B – Nginx | 40,000 | 56.50% | 80,000 | 86.17% | 15.36 MB |
B – Nginx(浅层解析) | 40,000 | 56.50% | 80,000 | 66.50% | 15.36 MB |
C – uprobe | 140 | 35.22% | 2,100 | 10.20% | 43.26 MB |
从上表能够看到:
- 场景 A:Agent 本身的 CPU 耗费仅为整机的 3.4%(相当于单核的 27%),相比业务耗费微不足道
- 场景 B:Agent 运行引发的额定 CPU 耗费与 Nginx 的基线 CPU 耗费相当(归一化至解决同样 RPS 数据之后),浅层解析下 Agent 的解决能力是 Nginx 的 1.2 倍
- 场景 C:Agent 本身的 CPU 耗费仅为单核的 10.20%
- 各个场景下的内存开销极低
除了评估 Agent 在业务高负载状况下的资源耗费,咱们也通过如下四个场景来评估 Agent 在 1C1G 资源限度下的极限解决能力。
场景 B – 应用 Nginx 压测 RPS:咱们通过 wrk2 注入了极其的 45K/s TPS 压力,此时 Nginx 的基线 CPU 耗费已高达 62.39%,能够看到这是一个十分极其的场景。在这样的场景下咱们失去了 Agent 在 1C 限度下的 HTTP 流量极限采集能力 —— 90K/s。
该场景下的局部测试数据如下(更多测试数据请查看 DeepFlow 在线 Demo 中的 Grafana Dashboard):
TPS | 采集 Span/s | Agent CPU | Agent CPU(浅层解析) | Agent MEM |
---|---|---|---|---|
45,000 | 90,000 | 98% | 77% | 15MB |
40,000 | 80,000 | 86% | 67% | 15MB |
35,000 | 70,000 | 75% | 58% | 15MB |
30,000 | 60,000 | 63% | 50% | 15MB |
场景 D – 应用 TCP client/server 压测 CPS:咱们应用 tcp_client 产生了 122K 个 IP-Port 五元组不同的、继续沉闷的 Flow,新建连贯速率约为 1K/s。此时 Agent 的内存耗费已达到 1GB,具体性能数据见下表。
Agent CPU | Agent 内存 | 流量 BPS | 流量 PPS | 流量 CPS |
---|---|---|---|---|
35.00% | 1079.77 MB | 23.43Mbps | 40.66Kpps | 121,771 |
场景 E – 应用 iperf3 压测 BPS:咱们应用 iperf3 产生了 20Gbps 的流量。这个场景下咱们并没有压到 Agent 的极限,20Gbps 曾经是咱们能在测试虚拟机中结构出的最大流量了。具体性能数据见下表。
Agent CPU | Agent 内存 | 流量 BPS | 流量 PPS |
---|---|---|---|
10.54% | 124.03 MB | 20.08Gbps | 114.51Kpps |
场景 F – 应用 udp_flood 压测 PPS:咱们应用 udp_flood 产生了 1.28Mpps 的流量。这个场景下将 Agent CPU 压到了单核的 95%。具体性能数据见下表。
Agent CPU | Agent 内存 | 流量 BPS | 流量 PPS |
---|---|---|---|
95.86% | 122.97M | 1.04Gbps | 1.28Mpps |
总结
通过六个场景的全方位评测,咱们对 Agent 的性能有了残缺的理解,心愿可能帮忙大家尽快落地基于 eBPF 的可观测性。简要论断总结如下:
-
对于一个典型的微服务架构的云原生业务,在注入整机 52% 高负载的压力下:
- Agent 对业务 TPS 没有任何影响
- Agent 使得业务 P50 RT 仅减少了 10.30ms(+14.76%),均匀每个调用的 RT 仅减少 0.8ms
- Agent 使得业务 CPU 仅增长 0.24%(+0.46%),简直感知不到
- Agent 本身仅耗费 3.4% CPU、47 MB 内存
-
对于一个极致性能的极简业务(Nginx Default Page),在注入单核 56% 高负载的压力下:
- Agent 对业务 TPS 没有任何影响
-
Agent 使得业务 P50 RT 仅减少了 0.13ms(+12.75%)
- 浅层解析时,业务 P50 RT 仅减少 0.08ms (+7.27%)
-
Agent 的解决性能等于 Nginx,解决等量 HTTP 调用的资源开销与 Nginx 雷同
- 浅层解析时,Agent 解决性能可高达 Nginx 的 1.2 倍
-
对于须要应用 eBPF uprobe 的业务场景(Golang 协程跟踪),在注入单核 35% 负载的压力下:
- Agent 对业务 TPS 没有任何影响
- Agent 使得业务 P50 RT 仅减少了 0.62ms(+17.42%)
- Agent 使得业务 CPU 增长了 9.58%(+27.20%),次要由 uprobe 的内核态 - 用户态上下文切换引入
- 比照:此场景下 DeepFlow 的性能为 Pixie 计划的 2.5 倍
-
在资源受限为 1 核 CPU 1GB 内存的状况下,Agent 的极限解决性能如下
- RPS:HTTP 采集性能 90K RPS,此时 Agent 耗费单核的 98% CPU
- CPS:采集 并发 122K CPS、新建 1K CPS 的 TCP Flood 流量,Agent 耗费 1GB 内存
- BPS:采集 20Gbps TCP Flood 流量,Agent 仅耗费单核的 10% CPU,仅耗费 124MB 内存
- PPS:采集 1.28Mpps UDP Flood 流量,Agent 耗费单核的 96% CPU
最初,本文所有测试数据(除浅层解析外)均是在 Agent 默认配置下测得的。理论业务环境中对于每一个调用,Agent 通常会在 过程、Pod 网卡、Node 网卡 三个地位采集到三个 Span,你能够按需敞开某些地位的数据采集,以取得更好的性能体现。实践受骗仅采集其中一份数据时,你能够取得 3 倍于本文的性能体现。咱们也期待社区小伙伴的更多评测。Enjoy DeepFlow!Enjoy Zero Code Observability!
什么是 DeepFlow
DeepFlow 开源我的项目旨在为简单的云原生利用提供深度可观测性。DeepFlow 基于 eBPF 实现了零插桩(Zero Code)、全笼罩(Full Stack)的指标、追踪、日志采集,并通过智能标签技术实现了所有观测数据的全关联(Universal Tagging)和高效存取。应用 DeepFlow,能够让云原生利用主动具备深度可观测性,从而打消开发者一直插桩的沉重负担,并为 DevOps/SRE 团队提供从代码到基础设施的监控及诊断能力。
GitHub 地址:https://github.com/deepflowio/deepflow
拜访 DeepFlow Demo,体验零插桩、全笼罩、全关联的可观测性。
原文地址,请拜访 DeepFlow 官网博客