Envoy 基础架构回顾:Listener、Cluster、Endpoint、Filter 链、线程模型与事件驱动

在深入缓存命中巡检之前,必须重新梳理 Envoy 的核心架构。Envoy 并非简单的反向代理,而是一个基于 事件驱动 和 多线程模型 构建的高性能数据面。理解其内部组件如何协作,是后续调优缓存命中率、排查性能瓶颈的基石。

核心组件与数据流

Envoy 的架构围绕四个核心抽象构建:Listener、Filter 链、Cluster 和 Endpoint。一个典型的请求处理路径如下:

  1. Listener 在指定端口(如 80、443)上接收入站连接。
  2. 连接建立后,数据流经 Listener Filter 链(如 TLS 终止、代理协议解析)。
  3. 进入 Network Filter 链(如 HTTP 连接管理器,HCM),解析协议。
  4. HCM 内部创建 HTTP Filter 链(如 Router、RBAC、Local Rate Limit)。
  5. Router Filter 根据路由规则选择目标 Cluster。
  6. Cluster 通过负载均衡算法从 Endpoint 列表中选择一个上游主机。
  7. 请求被转发至选中的 Endpoint,响应沿原路径返回。
关键认知: 缓存命中巡检主要作用于 HTTP Filter 链 中的 Local Cache Filter 或 External Cache Filter。Filter 在链中的位置决定了缓存逻辑是在路由之前还是之后执行。

组件职责对比

组件 职责 性能关注点
Listener 监听端口、接受连接、管理 TLS 连接数、accept 队列深度、TLS 握手开销
Filter 链 请求/响应的拦截、转换、路由、缓存 Filter 执行顺序、内存分配、编解码开销
Cluster 定义上游服务组、负载均衡策略、健康检查 连接池大小、健康检查频率、负载均衡算法
Endpoint 具体的上游主机 IP:Port 响应时间、错误率、断路器状态

线程模型:主线程 + Worker 线程

Envoy 采用 1 主线程 + N Worker 线程 的模型,这是其高性能的核心设计之一。

  • 主线程: 负责配置管理(xDS 监听)、统计刷新、进程管理。不处理任何数据面流量。
  • Worker 线程: 每个 Worker 拥有独立的 事件循环(Event Loop),处理一组 Listener 上的连接。连接一旦被分配给某个 Worker,其整个生命周期(读、写、Filter 处理)都在该 Worker 内完成,无需加锁。
调优启示: Worker 线程数通常设置为 CPU 核心数。对于缓存场景,如果 Worker 线程数过多,会导致 CPU 缓存(L1/L2)频繁失效,反而降低缓存查找性能。建议从 --concurrency 2 开始测试,逐步增加。
Envoy 线程模型与事件驱动架构 主线程 (Main) 配置管理 / xDS / 统计 分发 Listener & 配置 Worker 线程 1 事件循环 (Event Loop) 连接 1 | 连接 2 | 连接 3 Filter 链处理 (无锁) Worker 线程 2 事件循环 (Event Loop) 连接 4 | 连接 5 | 连接 6 Filter 链处理 (无锁) Worker 线程 N 事件循环 (Event Loop) 连接 7 | 连接 8 | 连接 9 Filter 链处理 (无锁) 事件驱动核心:epoll / kqueue / io_uring Worker 线程通过非阻塞 I/O 多路复用处理数千连接,无锁竞争 连接分配策略:轮询 (Round Robin) 或 源地址哈希,绑定后不再迁移

Filter 链:可插拔的处理管道

Filter 是 Envoy 扩展性的灵魂。一个请求在 Worker 线程内会依次经过三类 Filter:

  1. Listener Filter: 在连接建立初期执行,用于 TLS 卸载、代理协议解析、原始目的地址检测。
  2. Network Filter: 工作在 L4/L7 边界,核心是 HTTP Connection Manager (HCM),负责将字节流解码为 HTTP 请求/响应。
  3. HTTP Filter: 工作在 HTTP 层,是缓存、路由、限流、故障注入等功能的载体。
缓存 Filter 放置规则: 如果使用 本地缓存(如基于 LRU 的 Cache Filter),应放在 Router Filter 之前,以便直接命中缓存并短路转发。如果使用 外部缓存(如 Redis),则通常放在 Router Filter 之后,因为需要先确定上游 Cluster 才能构造缓存 Key。
Envoy Filter 链处理流程 入站连接 Listener Filter TLS 终止 代理协议 Network Filter HTTP 解码 连接管理 HTTP Filter 链 ① 缓存 Filter ② Router Filter ③ 限流 Filter ④ 故障注入 上游 Cluster 缓存 Filter 位置策略 本地缓存 → 放在 Router 之前(短路);外部缓存 → 放在 Router 之后(依赖 Cluster 信息)

事件驱动与无锁设计

Envoy 的 Worker 线程完全基于 事件驱动(epoll/kqueue/io_uring),每个 Worker 内部维护一个事件循环。当一个连接上有数据可读时,Worker 线程读取数据并驱动 Filter 链处理。由于每个连接只属于一个 Worker,所有 Filter 操作(包括缓存查找)都在单线程内完成,无需互斥锁。

性能调优要点:
  • 连接均衡: 使用 --concurrency 控制 Worker 数量,避免过多 Worker 导致上下文切换和 CPU 缓存抖动。
  • Filter 顺序: 将计算密集或可能短路的 Filter(如缓存)尽量前置,减少后续 Filter 的执行次数。
  • 线程局部缓存: 对于本地缓存场景,每个 Worker 可以维护独立的 LRU 缓存实例,彻底消除锁竞争,但会牺牲缓存总容量(N 个 Worker 有 N 份缓存副本)。

小结

Envoy 的架构设计围绕 无锁事件驱动 和 可插拔 Filter 链 展开。Listener 负责接入,Cluster/Endpoint 负责后端寻址,而 Filter 链则是所有业务逻辑(包括缓存)的执行场所。理解 Worker 线程的隔离性,对于后续设计缓存策略、评估命中率、定位性能瓶颈至关重要。