Envoy 性能基准测试实战指南:从构建、配置到测量的最佳实践
【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy
Envoy 是一个云原生高性能边缘/中间/服务代理,但"Envoy 到底有多快"并没有一个放之四海而皆准的答案。本文以 docs/root/faq/performance/how_to_benchmark_envoy.rst 为骨架,系统梳理 Envoy 官方给出的基准测试最佳实践:从正确的二进制构建、--concurrency线程模型,到关闭 circuit breaking、generate_request_id、dynamic_stats等影响测量的配置项,再到负载生成器选型、统计校验与perf剖析。读完本文,你将掌握一套可复现、可对照、可审查的 Envoy 性能基准测试方法论,能够在自己的环境中得到可信的 QPS 与延迟数据。
一、为什么 Envoy 没有一个官方基准数字
任何针对 Envoy 的基准测试,首先要接受一个前提:不存在单一的 QPS、延迟或吞吐开销数字能够刻画 Envoy 这类网络代理。Envoy 官方在 docs/root/faq/performance/how_fast_is_envoy.rst 中明确说明:"它取决于具体情况"——性能在很大程度上取决于启用了哪些 Envoy 特性以及运行环境,而且做精确的性能测试本身就是一项极其困难的工作,项目团队目前没有资源去维护官方基准。
Envoy 团队在关键路径上做了大量性能调优,相信其表现优异,但并不发布任何官方 benchmark。官方鼓励用户在自己的环境中,使用与生产计划类似的配置来对 Envoy 做基准测试。因此本文提供的就是一套"上下文感知"(contextually aware)的测试规范,确保与其他系统对比时做到 apples-to-apples 的公平比较,而不是追求一个脱离场景的绝对数字。
二、构建基准:用正确的二进制做测试
性能测试的第一步是确保被测对象本身是"发布级"的,否则结果没有任何参考价值:
- 使用 release 版本的 Envoy 二进制。如果自己构建,必须在 Bazel 命令行中使用
-c opt,否则默认的调试构建(-c dbg)会带来显著的性能失真,无法代表真实运行表现。 - 使用最新的 point release。Envoy 开发节奏很快,老版本在性能上往往落后于当前版本,用旧版本得出的结论不足以代表 Envoy 的真实性能水平。
- 若基于 main 分支开发构建,请做足功课:确认在你的 benchmark 工作附近没有合入性能回退(regression)或性能改进的提交,并且尽量贴近 HEAD。这一点可以通过检查
changelogs/目录下对应版本的变更记录来辅助判断。
构建产物通常位于 Bazel 的bazel-bin/source/exe/envoy(具体路径取决于构建配置),基准测试请始终使用该优化后的产物。
三、并发模型:正确设置--concurrency
Envoy 采用多 worker 线程模型,每个 worker 线程独立运行事件循环,处理各自监听 socket 上的连接。从 source/server/active_udp_listener.cc 的实现可以看到,worker_index与concurrency是驱动监听器分配的核心参数,所有连接都会被分发到具体的 worker 线程。
针对--concurrency官方建议:
- 不设置该标志,让 Envoy 默认按机器的逻辑核心数创建 worker 线程(每逻辑核一个线程);
- 或者显式设置为与对比系统中其他网络代理可用的核心/线程数一致,以保证对比公平。
一个必须牢记的细节:Envoy 会把同一连接上的所有 stream 分配到同一个 worker 线程。这意味着如果负载生成器只建立了一条 HTTP/2 连接,那么即便机器有 72 个逻辑核、72 个 worker 线程,实际也只有 1 个 worker 线程在工作。低连接数 + 完美 keep-alive 的基准测试尤其容易踩到这个坑,后面"负载生成器"一节会进一步展开。
四、配置基线:关掉会干扰测量的特性
基准测试配置的核心原则是:bootstrap 或 xDS 配置中每一行都应有动机,都是该测试场景所必需的。以下是官方点名要求调整的关键项。
4.1 关闭熔断(circuit breaking)
基准测试中最常见的问题之一:Envoy 默认的熔断阈值偏低,导致测试中出现连接和请求排队,QPS 与延迟被严重扭曲。官方 FAQ docs/root/faq/load_balancing/disable_circuit_breaking.rst 指出:Envoy 目前没有一个开关能彻底关闭熔断,但可以通过把阈值设到极大值来等效禁用。下面这份配置将各类阈值设为1000000000(接近std::numeric_limits<uint32_t>::max()的语义),覆盖 DEFAULT 与 HIGH 两个优先级:
circuit_breakers: thresholds: - priority: DEFAULT max_connections: 1000000000 max_pending_requests: 1000000000 max_requests: 1000000000 max_retries: 1000000000 - priority: HIGH max_connections: 1000000000 max_pending_requests: 1000000000 max_requests: 1000000000 max_retries: 1000000000字段定义见 api/envoy/config/cluster/v3/circuit_breaker.proto:max_connections限制到上游集群的最大连接数,max_pending_requests限制等待可用连接的排队请求数,max_requests限制任意时刻在途的最大请求数,max_retries限制重试请求数。Envoy 支持在路由级别做优先级路由,你可以据此调整对应优先级的阈值。
4.2 关闭generate_request_id
HTTP 连接管理器默认会为每个请求生成x-request-id头(UUID4)。在 api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto 的字段注释中写得非常直白:生成随机 UUID4 是昂贵的(expensive),在高吞吐场景下如果不需要该特性,应将其关闭。配置如下:
http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager generate_request_id: false4.3 关闭dynamic_stats,必要时用reject_all禁用全部统计
Router 过滤器默认会生成动态集群统计(dynamic cluster statistics),默认值为true,在高性能场景下可以禁用。字段定义见 api/envoy/extensions/filters/http/router/v3/router.proto:
http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router dynamic_stats: false如果你的目标是测量 Envoy相对于直连(direct connection)的开销,那么应该考虑把统计功能整体关掉。通过stats_config中的 StatsMatcher.reject_all 可以实现:当reject_all为true时,不会实例化任何统计(no stats will be instantiated),将统计开销降到零:
stats_config: stats_matcher: reject_all: true4.4 对齐网络与 HTTP 过滤器链
确保被测的 networking 与 HTTP 过滤器链,与对比系统中启用的特性是可比的。例如你对比的是一个直连的裸 TCP 转发,就不要在 Envoy 这边挂上一堆认证、限流、熔断等过滤器;反之亦然。过滤器的数量与复杂度直接决定每请求的开销,任何不对称都会让对比结论失真。
4.5 使用现实的 TLS 配置
如果测试包含 TLS:
- 确保 TLS 设置是现实的(符合真实部署场景),并且在对比中使用一致的 cipher 套件;
- 会话复用(session reuse)对结果影响显著,必须通过监听器 SSL 统计跟踪其行为。
Envoy 的 TLS 统计根植于listener.<address>.ssl.*,详见 docs/root/configuration/listeners/stats.rst。例如ssl.handshake相关计数可用于判断握手次数与会话复用是否如预期,避免"测试里大量 TLS 握手但配置却是关闭复用"这类失真场景。
4.6 统一 HTTP/2 设置
HTTP/2 的流量控制与流并发参数必须保证对比双方一致。核心字段定义在 api/envoy/config/core/v3/protocol.proto 的Http2ProtocolOptions消息中:
max_concurrent_streams(字段 2):单个连接上允许的并发 stream 上限;initial_stream_window_size(字段 3):单条 stream 级别的流量控制窗口;initial_connection_window_size(字段 4):连接级别的流量控制窗口。
理想情况下,优化这些 HTTP/2 设置时要结合 BDP(带宽延迟积)与网络链路延迟。举一个直观的例子:如果客户端与 Envoy 之间存在高延迟链路,而过小的initial_connection_window_size会限制在途数据量,导致吞吐远低于理论值;这与被测系统的 HTTP/2 参数不一致时,就会得出错误的对比结论。
五、验证实验结果:监听器与集群统计
每次实验都要在监听器(listener)和集群(cluster)统计中核实 stream 数、连接数与错误数是否符合预期。这是排除配置事故的最快手段,例如:
- listener 的
downstream_cx_active、downstream_rq_active应反映负载生成器的连接/请求规模; - cluster 的
upstream_cx_total、upstream_rq_total应等于预期的上游流量; - 任何错误计数(如
upstream_rq_5xx、cx_connect_fail)的异常增长都提示配置或环境问题。
如果统计数字与实验设计对不上,那么后续的 QPS/延迟数据再漂亮也是无效的。相关统计字段可对照 docs/root/configuration/listeners/stats.rst 与集群统计文档逐项核对。
六、负载生成器:最容易引入偏差的一环
负载生成器的行为会直接进入测量结果,以下是官方重点提醒的几个维度。
6.1 连接在 worker 线程间的分布
如第三节所述,Envoy 将同一连接的所有 stream 固定分配到一个 worker 线程。因此:
- 使用低连接数 + 完美 keep-alive的基准测试时,必须清楚你的连接落在哪几个 worker 上;
- 72 核机器只开一条 HTTP/2 连接,结果只能反映单 worker 的性能,而不是 Envoy 的多核吞吐能力。
6.2 请求释放(request-release)时序
某些负载生成器会产生天然抖动(jittery)或成批(batchy)的请求释放时序,这可能意外地成为某些测试的主导因素。应确保请求释放时序与测试意图一致——如果你想测的是稳定状态下的吞吐,就不要让负载生成器以突发模式注入请求。
6.3 连接复用策略
负载生成器如何复用连接(MRU、随机、LRU 等)会直接影响工作分布。不同的复用策略决定了连接在不同 worker 上的聚集程度,进而影响吞吐与尾部延迟,必须在对比测试中保持一致。
6.4 小延迟测量的灵敏度
如果目标是测量很小的延迟(例如 < 1ms),请确保测量工具和环境具备相应的灵敏度,且噪声地板(noise floor)足够低。测量工具自身的时钟分辨率、调度抖动、内核 tick 等都会成为瓶颈,此时测出来的数字反映的可能是工具而非 Envoy。
6.5 推荐的负载生成器:Nighthawk
官方明确建议考虑使用 Nighthawk 作为负载生成与测量工具——Envoy 项目组承诺在该工具中持续建设 benchmark 与延迟测量最佳实践。它天然与 Envoy 的统计模型、HTTP/2 语义契合,能显著降低"负载工具偏差"。
七、剖析与延迟测量:让数字经得起推敲
7.1 用perf验证 CPU 花在了该花的地方
在 benchmark 运行期间,对 Envoy 进程采集perfprofile 并生成火焰图(flame graphs)。目的是验证 Envoy 的时间确实花在了预期的关键工作上,而不是某些无关或边缘的工作上。例如:
- 如果火焰图中大量时间耗在
generate_request_id的 UUID4 生成上,说明配置基线没做好(对应 4.2 节); - 如果时间大量耗在统计相关的原子操作上,说明
reject_all或dynamic_stats该启用了(对应 4.3 节)。
7.2 延迟测量:永远不要在最大负载下测延迟
熟悉延迟测量最佳实践至关重要,其核心结论是:
- 绝不要在最大负载(max load)下测量延迟——这通常没有意义,也不能反映系统真实性能;
- 应在 QPS-延迟曲线的拐点(knee)以下测量延迟;
- 优先使用开放回路(open loop)负载生成器,而不是闭合回路(closed loop)——闭合回路生成器会等待响应后再发下一个请求,天然耦合了被测系统的延迟,扭曲结果。
7.3 避免 benchmark 反模式
最后,请警惕常见的"benchmarking crimes"(基准测试罪行),例如:比较不同硬件上的结果、忽略实验环境差异、只报最优值不报分布、在过小的样本上做结论等。一份可信的基准报告应当包含完整的实验条件、配置版本与原始数据。
八、Checklist:一次可信的 Envoy 基准测试
综合全文,给出可执行的核对清单:
| 阶段 | 检查项 | 依据 |
|---|---|---|
| 构建 | release 二进制;Bazel 加-c opt;使用最新 point release;main 分支测试贴近 HEAD | docs/root/faq/performance/how_to_benchmark_envoy.rst |
| 并发 | --concurrency不设置(每逻辑核一线程)或与对比系统线程数一致 | 同上 |
| 配置 | 熔断阈值设为极大值(max_connections等四项 × DEFAULT/HIGH) | docs/root/faq/load_balancing/disable_circuit_breaking.rst |
| 配置 | generate_request_id: false | http_connection_manager.proto |
| 配置 | dynamic_stats: false;对比直连开销时reject_all: true | router.proto、stats.proto |
| 配置 | 过滤器链对齐、TLS cipher/会话复用一致、HTTP/2 流控参数一致 | protocol.proto |
| 验证 | 核对 listener/cluster 的 stream、连接、错误统计 | docs/root/configuration/listeners/stats.rst |
| 负载 | 关注连接在 worker 间的分布、请求释放时序、连接复用策略 | docs/root/faq/performance/how_to_benchmark_envoy.rst |
| 剖析 | perf火焰图确认 CPU 花在关键路径;延迟在曲线拐点以下测量;优先 open loop | 同上 |
按此清单逐项落实,你得到的 Envoy 基准测试结果将具备可重复性、公平性与说服力,能够在不同配置、不同系统之间进行真正有意义的横向比较。
【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考