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 代理的完整数据流:
2.2 Downstream 连接生命周期
Downstream 连接是指客户端(如浏览器、微服务 A)到 Envoy 监听器之间的连接。Envoy 对 Downstream 连接的管理遵循严格的状态机:
- 监听(Listening):Envoy 在配置的地址(如 0.0.0.0:8080)上创建 Listener,等待客户端发起 TCP 连接。
- 接受(Accept):内核完成 TCP 三次握手后,Envoy 的 Worker 线程通过 epoll/kqueue 获取新连接的文件描述符。
- TLS 握手(TLS Handshake):如果 Listener 配置了 TLS 证书,Envoy 在此阶段完成 Server Hello、证书交换、密钥协商。
- 过滤器链执行(Filter Chain):连接进入 L4 过滤器链(如 TCP 代理、原始数据解析),然后根据协议进入 L7 过滤器链(如 HTTP 连接管理器)。
- 请求处理(Request Processing):对于 HTTP 连接,Envoy 解析请求头、匹配路由、执行限流/鉴权等 L7 策略。
- 连接关闭(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 如何协调两端连接的生命周期:
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);空闲超时按场景调,长连接服务设大值,短连接服务设小值。