3. Envoy 数据面架构:线程模型、连接池与核心资源

Envoy 作为高性能数据面代理,其架构设计直接决定了数据包处理路径的效率和资源消耗。理解 Envoy 的线程模型、连接池机制以及 Listener/Cluster/Endpoint 三大核心概念,是分析 CNI 缓存命中瓶颈的前提。Envoy 采用单进程多线程架构,通过事件驱动和异步非阻塞 I/O 实现高吞吐与低延迟。

3.1 Envoy 线程模型:主线程与 Worker 线程

Envoy 的线程模型分为三类角色:主线程(Main Thread)、Worker 线程 和 文件刷新线程(File Flush Thread)。主线程负责配置加载、证书轮换、统计刷新等控制面任务;Worker 线程负责处理所有网络 I/O 和连接事件;文件刷新线程仅负责异步写入访问日志。

关键设计原则: 所有 Worker 线程之间不共享连接,每个 Worker 拥有独立的连接池和事件循环,从而避免锁竞争,实现近乎线性的多核扩展。

下图展示了 Envoy 的线程模型与数据流关系:

Envoy 线程模型与数据流 主线程 (Main) 配置加载 / 证书轮换 / 统计 配置分发 Worker 线程池 (通常 = CPU 核数) Worker 0 事件循环 Worker 1 事件循环 Worker N 事件循环 连接池 (独立) 连接池 (独立) 连接池 (独立) 入站流量 客户端请求 连接分配 (轮询 / 哈希) 出站流量 上游集群 Worker 通过连接池转发 文件刷新线程 异步日志写入 说明:每个 Worker 线程拥有独立的连接池和事件循环,无锁竞争;主线程仅处理控制面任务,不参与数据面转发。
性能要点: Worker 线程数量通常设置为物理 CPU 核数。过多的 Worker 会导致上下文切换开销增加,过少则无法充分利用多核能力。在 CNI 缓存场景中,Worker 线程的亲和性设置会影响连接池的缓存命中率。

3.2 连接池:连接复用与缓存

Envoy 的连接池是数据面性能的核心组件。每个 Worker 线程为每个上游集群维护独立的连接池,连接池按 协议类型(HTTP/1.1、HTTP/2、TCP)和 上游端点 进行分桶。连接池的核心目标是减少连接建立开销,提高连接复用率。

连接池类型 复用策略 最大连接数 空闲超时 适用场景
HTTP/1.1 连接池 请求级复用(Keep-Alive) 可配置(默认 1024) 可配置(默认 1h) 传统 HTTP 服务
HTTP/2 连接池 多路复用(流级) 通常 1 条连接 可配置 gRPC / 微服务
TCP 连接池 无复用(透传) 无限制 无 原始 TCP 代理
CNI 缓存关联: 连接池的缓存命中率直接影响数据面延迟。当连接池中的连接因上游端点变更(Pod 扩缩容)而频繁失效时,Worker 线程需要重新建立连接,导致 CNI 缓存查找和连接建立的双重开销。这是 CNI 缓存命中瓶颈分析的关键切入点。

3.3 Listener / Cluster / Endpoint 核心概念

Envoy 的配置模型围绕三个核心资源构建:Listener(监听器)、Cluster(集群)和 Endpoint(端点)。这三者构成了数据面转发的完整链路。

3.3.1 Listener(监听器)

Listener 定义了 Envoy 如何接收入站流量。每个 Listener 绑定一个 IP:Port,并关联一组过滤器链(Filter Chain)来处理协议解析和路由决策。Listener 可以配置多个地址,支持透明代理和端口复用。

listeners:
- name: ingress_listener
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 80
  filter_chains:
  - filters:
    - name: envoy.filters.network.http_connection_manager
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
        stat_prefix: ingress_http
        route_config:
          name: local_route
          virtual_hosts:
          - name: backend
            domains: ["*"]
            routes:
            - match:
                prefix: "/"
              route:
                cluster: backend_cluster

3.3.2 Cluster(集群)

Cluster 定义了 Envoy 如何将流量转发到一组上游服务。每个 Cluster 包含连接池配置、负载均衡策略、健康检查规则以及服务发现类型(静态、DNS、EDS 等)。Cluster 是连接池的归属单位。

Cluster 属性 说明 典型值
type 服务发现方式 STATIC / STRICT_DNS / EDS / LOGICAL_DNS
connect_timeout 连接超时 0.25s
per_connection_buffer_limit_bytes 连接缓冲区大小 32768 (32KB)
lb_policy 负载均衡策略 ROUND_ROBIN / LEAST_REQUEST / RING_HASH / MAGLEV
circuit_breakers 熔断配置 max_connections / max_pending_requests / max_requests

3.3.3 Endpoint(端点)

Endpoint 是 Cluster 下的具体上游实例,通常对应一个 Pod 的 IP:Port。Endpoint 由服务发现机制动态更新,Envoy 通过 EDS(Endpoint Discovery Service)从控制面获取最新的端点列表。每个 Endpoint 可以携带健康状态、权重、区域等元数据。

clusters:
- name: backend_cluster
  type: EDS
  eds_cluster_config:
    eds_config:
      path: /etc/envoy/eds.conf
  lb_policy: LEAST_REQUEST
  connect_timeout: 0.25s
  circuit_breakers:
    thresholds:
    - priority: DEFAULT
      max_connections: 1000
      max_requests: 2000

下图展示了 Listener → Cluster → Endpoint 的完整转发链路:

Envoy 核心资源转发链路 客户端 请求发起 Listener 0.0.0.0:80 过滤器链 Cluster 连接池 负载均衡 健康检查 Endpoints Pod A: 10.0.1.1:8080 Pod B: 10.0.1.2:8080 Pod C: 10.0.1.3:8080 ... 转发流程说明: 1. 客户端请求到达 Listener,经过过滤器链解析协议和路由。 2. Listener 根据路由规则选择目标 Cluster。 3. Cluster 从连接池中获取或创建到 Endpoint 的连接,执行负载均衡后转发请求。

3.4 核心概念与 CNI 缓存的协同关系

在 Kubernetes 环境中,Envoy 的 Listener/Cluster/Endpoint 与 CNI 缓存存在以下协同关系:

  • Endpoint 变更触发 CNI 缓存失效: 当 Pod 扩缩容或迁移时,Endpoint 列表发生变化,Envoy 通过 EDS 获取更新。此时,Worker 线程的连接池中指向旧 Endpoint 的连接需要被销毁,新连接需要重新建立。CNI 缓存中的路由条目也可能因 Pod IP 变化而失效。
  • 连接池复用降低 CNI 缓存查找频率: 高连接复用率意味着每个连接可以处理多个请求,从而减少每次请求的 CNI 缓存查找次数。连接池的命中率越高,CNI 缓存的压力越小。
  • Worker 线程隔离影响缓存局部性: 每个 Worker 线程拥有独立的连接池,这意味着 CNI 缓存条目可能被多个 Worker 线程重复缓存。如果 Worker 线程数过多,CNI 缓存的重复条目会增加内存开销,但可以减少跨线程竞争。
性能调优建议: 在 CNI 缓存命中瓶颈分析中,应重点关注以下指标:连接池复用率(cluster.upstream_cx_active / cluster.upstream_rq_active)、Endpoint 变更频率(eds.cluster_update_attempt)、以及每个 Worker 线程的连接池大小。这些指标直接反映了 CNI 缓存与 Envoy 数据面的协同效率。