2. Envoy 通信基础:L3/L4/L7 代理原理与连接生命周期管理

Envoy 作为高性能服务网格数据面,其通信模型建立在 OSI 模型的 L3/L4/L7 分层代理之上。理解这三层代理原理以及 Downstream(下游)与 Upstream(上游)连接的生命周期,是调优 Envoy 通信机制的前提。本章将拆解 Envoy 的分层代理架构,并详细描述连接从建立到销毁的完整过程。

2.1 L3/L4/L7 代理原理

Envoy 并非单纯的 HTTP 代理,而是一个支持多协议、多层次的代理引擎。其核心能力覆盖网络栈的三个关键层次:

层次 OSI 模型对应 Envoy 实现机制 典型应用场景
L3 代理 网络层 原始 IP 包转发(基于 TUN 接口或 IP 透明代理) 透明代理、流量拦截、VPN 网关
L4 代理 传输层 TCP/UDP 连接转发(Listener + Cluster 直连) TCP 代理、Redis/MongoDB 代理、TLS 终结
L7 代理 应用层 HTTP/2、gRPC、HTTP/1.1 协议解析与路由 微服务路由、限流、熔断、Header 修改
关键认知: Envoy 的 L4 过滤器链和 L7 过滤器链是独立的。一个监听器可以同时配置 L4 和 L7 过滤器,Envoy 会先执行 L4 过滤器(如 TLS 终止、TCP 代理),再根据协议类型决定是否进入 L7 过滤器(如 HTTP 连接管理器)。

下图展示了 Envoy 在单个监听器上处理 L3/L4/L7 代理的完整数据流:

Envoy 分层代理数据流(L3 → L4 → L7) Downstream L3 代理 IP 透明拦截 原始套接字 L4 代理 TCP/UDP 转发 TLS 终结 L7 代理 HTTP/gRPC 路由/限流 Upstream 数据流双向经过所有代理层,L7 代理可复用 L4 建立的连接

2.2 Downstream 连接生命周期

Downstream 连接是指客户端(如浏览器、微服务 A)到 Envoy 监听器之间的连接。Envoy 对 Downstream 连接的管理遵循严格的状态机:

  1. 监听(Listening):Envoy 在配置的地址(如 0.0.0.0:8080)上创建 Listener,等待客户端发起 TCP 连接。
  2. 接受(Accept):内核完成 TCP 三次握手后,Envoy 的 Worker 线程通过 epoll/kqueue 获取新连接的文件描述符。
  3. TLS 握手(TLS Handshake):如果 Listener 配置了 TLS 证书,Envoy 在此阶段完成 Server Hello、证书交换、密钥协商。
  4. 过滤器链执行(Filter Chain):连接进入 L4 过滤器链(如 TCP 代理、原始数据解析),然后根据协议进入 L7 过滤器链(如 HTTP 连接管理器)。
  5. 请求处理(Request Processing):对于 HTTP 连接,Envoy 解析请求头、匹配路由、执行限流/鉴权等 L7 策略。
  6. 连接关闭(Close):客户端主动关闭、空闲超时(Idle Timeout)、或 Envoy 主动 Drain 时,连接进入 FIN 或 RST 状态。
调优要点: Downstream 连接的 idle_timeout 和 max_requests_per_connection 是控制连接复用率的关键参数。在 HTTP/2 场景下,建议将 max_requests_per_connection 设置为 0(无限复用),以减少连接重建开销。

2.3 Upstream 连接生命周期

Upstream 连接是指 Envoy 到后端服务(如微服务 B、数据库)之间的连接。Envoy 通过 Cluster 管理 Upstream 主机池,连接生命周期如下:

阶段 触发条件 Envoy 行为 关键配置
DNS 解析 Cluster 配置了 DNS 类型 异步解析域名,更新端点列表 dns_lookup_family, dns_refresh_rate
连接池初始化 收到第一个 Downstream 请求 按需创建到 Upstream 主机的 TCP 连接 max_connections, connect_timeout
TCP 连接建立 连接池中无可用连接 发起 TCP 三次握手,可选 TLS 握手 upstream_tls_context
请求复用 HTTP/2 多路复用或 HTTP/1.1 Keep-Alive 同一连接上发送多个请求 max_requests_per_connection
健康检查 定时或主动探测 发送 HTTP/TCP 探针,标记主机健康状态 health_checks, healthy_threshold
连接关闭 空闲超时、主机移除、Drain 发送 FIN 或 RST,从连接池移除 idle_timeout, drain_timeout

2.4 连接生命周期管理的关键机制

Envoy 通过以下机制确保 Downstream 与 Upstream 连接的高效管理:

  • 连接池(Connection Pool):每个 Worker 线程维护独立的 Upstream 连接池,避免跨线程锁竞争。连接池支持按主机、按协议(HTTP/1.1、HTTP/2)隔离。
  • 断路器(Circuit Breaker):在连接池层面设置 max_connections、max_pending_requests、max_requests、max_retries 四个阈值,防止 Upstream 被突发流量打垮。
  • Drain 机制(Drain Mechanism):在 Envoy 优雅关闭或 Cluster 更新时,Drain 阶段允许已有请求完成,但拒绝新请求。Drain 超时后强制关闭剩余连接。
  • 空闲超时(Idle Timeout):Downstream 和 Upstream 连接均可配置空闲超时。对于长连接场景(如 gRPC Stream),建议将空闲超时设置为 0 或较大值。
常见陷阱: 在 L7 代理模式下,如果 Downstream 使用 HTTP/2 而 Upstream 使用 HTTP/1.1,Envoy 会在内部进行协议转换。此时 Upstream 连接池的 max_connections 需要根据 HTTP/1.1 的并发限制(通常为 6-8)合理设置,否则容易触发断路器。

2.5 连接生命周期状态图

下图整合了 Downstream 和 Upstream 连接的核心状态转换,展示 Envoy 如何协调两端连接的生命周期:

Envoy 连接生命周期状态转换 Downstream 连接 Listening Accept TLS Handshake Active Drain / Close Upstream 连接 DNS Resolve Pool Init TCP Connect Active Idle / Close Downstream 的 Active 状态对应 Upstream 的 DNS Resolve → Pool Init → TCP Connect → Active 链路

2.6 实践建议与配置示例

以下是一个典型的 Envoy 配置片段,展示了 Downstream 和 Upstream 连接生命周期相关参数:

static_resources:
  listeners:
  - name: downstream_http
    address:
      socket_address: { address: 0.0.0.0, port_value: 8080 }
    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
          codec_type: AUTO
          # Downstream 连接空闲超时:60 秒
          idle_timeout: 60s
          # 每个 Downstream 连接最大请求数:0(无限)
          max_requests_per_connection: 0
          route_config:
            virtual_hosts:
            - name: backend
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route:
                  cluster: upstream_service
  clusters:
  - name: upstream_service
    connect_timeout: 5s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    # Upstream 连接池配置
    circuit_breakers:
      thresholds:
      - priority: DEFAULT
        max_connections: 1024
        max_pending_requests: 1024
        max_requests: 1024
        max_retries: 3
    # Upstream 连接空闲超时:300 秒
    idle_timeout: 300s
    # 每个 Upstream 连接最大请求数:100
    max_requests_per_connection: 100
    load_assignment:
      cluster_name: upstream_service
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address: { address: 10.0.1.10, port_value: 8081 }
调优口诀: Downstream 连接重复用(max_requests_per_connection: 0),Upstream 连接设上限(max_requests_per_connection: 100);空闲超时按场景调,长连接服务设大值,短连接服务设小值。