4. 连接断开类型:主动断开、被动断开、空闲超时断开、健康检查失败断开
在 Envoy 代理的日常运行中,连接断开是触发重试机制的直接原因。理解不同类型的连接断开,有助于精准配置重试策略,避免无效重试或重试风暴。Envoy 将连接断开归纳为四种核心类型:主动断开、被动断开、空闲超时断开和健康检查失败断开。每种类型在协议栈中的触发点、可重试性以及性能影响均有显著差异。
调优要点:并非所有断开都适合重试。主动断开通常由客户端或上游正常关闭引起,重试无意义;而被动断开(如 RST 包)往往暗示上游异常,是重试策略的主要作用对象。
4.1 四种断开类型对比
| 断开类型 | 触发场景 | TCP 层表现 | HTTP 层表现 | Envoy 默认重试行为 |
|---|---|---|---|---|
| 主动断开 | 客户端/上游正常关闭连接 | FIN 包(四次挥手) | Connection: close 头 | 不重试 |
| 被动断开 | 上游崩溃、超时、拒绝请求 | RST 包 | 5xx 状态码、流重置 | 可重试(默认最多 1 次) |
| 空闲超时断开 | 连接空闲超过 idle_timeout |
FIN 或 RST(取决于实现) | 流重置 | 不重试(连接已回收) |
| 健康检查失败断开 | 主动健康检查判定上游不健康 | Envoy 主动发送 RST | 无(健康检查独立于数据面) | 不重试(上游已被剔除) |
4.2 主动断开(Active Close)
主动断开是指连接的一方在完成数据传输后,按照协议规范正常关闭连接。在 TCP 层面表现为发送 FIN 包,完成四次挥手。Envoy 在以下场景会触发主动断开:
- 客户端主动关闭:HTTP/1.1 请求完成后,客户端发送
Connection: close头。 - 上游服务器主动关闭:上游处理完响应后,关闭连接以回收资源。
- Envoy 自身连接管理:达到最大连接数限制时,Envoy 会主动关闭最老的空闲连接。
主动断开是预期内的行为,Envoy 不会将其视为错误,因此不会触发重试。如果重试策略错误地将主动断开纳入重试范围,会导致大量无效连接建立,增加延迟和资源消耗。
4.3 被动断开(Passive Close / RST)
被动断开是连接因异常情况被强制终止,TCP 层表现为发送 RST 包。这是 Envoy 重试机制最关注的断开类型。常见触发原因包括:
- 上游进程崩溃:上游服务突然退出,操作系统内核发送 RST。
- 上游超时:上游在
upstream_request_timeout内未响应,Envoy 重置流。 - 上游拒绝连接:上游连接池已满或处于过载保护状态。
- 协议错误:上游返回格式错误的 HTTP 响应或非法帧。
性能影响:被动断开通常伴随连接池中的连接失效。Envoy 需要立即从连接池中移除该连接,并触发重试逻辑。如果被动断开率过高(>5%),应优先排查上游稳定性,而非单纯增加重试次数。
4.4 空闲超时断开(Idle Timeout)
Envoy 为每个连接维护一个空闲计时器。当连接在 idle_timeout 时间内没有任何数据传输时,Envoy 会主动断开该连接以释放资源。这是连接池管理的关键机制。
关键配置参数:
| 参数 | 默认值 | 推荐值(高并发场景) | 说明 |
|---|---|---|---|
idle_timeout |
1 小时 | 5-10 分钟 | 连接空闲超过此时间即断开 |
max_connection_duration |
无限制 | 30 分钟 | 连接最大存活时间,防止长连接泄漏 |
空闲超时断开是正常资源回收行为,Envoy 不会将其视为上游错误,因此不触发重试。调优时需注意:过短的 idle_timeout 会导致频繁断开和重建连接,增加 TCP 握手开销;过长的 idle_timeout 则可能占用大量内存和文件描述符。
4.5 健康检查失败断开(Health Check Failure)
Envoy 通过主动健康检查(Active Health Check)定期探测上游端点。当端点连续失败次数超过 unhealthy_threshold 时,Envoy 将其标记为不健康,并主动断开该端点上的所有现有连接。
健康检查断开的特点:
- 触发方式:由 Envoy 的健康检查线程主动发起,独立于数据面请求。
- 断开范围:断开该上游端点上的所有连接,而非单条连接。
- 重试行为:Envoy 不会对健康检查失败的连接进行重试,因为上游已被从负载均衡池中剔除。
- 恢复机制:当健康检查再次成功(连续成功次数达到
healthy_threshold),端点重新加入池,新连接开始建立。
避坑指南:健康检查失败断开可能导致连接池雪崩。如果健康检查间隔过短(如 1 秒),且上游短暂抖动,Envoy 可能快速剔除大量端点,导致剩余端点瞬时压力激增。建议将健康检查间隔设置为 5-10 秒,并配合
panic_threshold(恐慌阈值)使用。
4.6 断开类型与重试决策流程
Envoy 在决定是否重试时,会按以下流程判断断开类型:
- 检查是否为主动断开:如果是 FIN 包或
Connection: close,直接返回,不重试。 - 检查是否为健康检查失败断开:如果上游已被标记为不健康,不重试,直接返回 503。
- 检查是否为空闲超时断开:如果连接因空闲超时被回收,不重试。
- 检查是否为被动断开:如果是 RST 包或 5xx 响应,进入重试逻辑,检查重试次数、重试预算和重试策略。
4.7 性能调优建议
- 区分断开类型监控:在 Envoy 的
stats中,通过downstream_cx_destroy和upstream_cx_destroy指标区分主动与被动断开。如果被动断开占比超过 20%,应优先优化上游稳定性。 - 空闲超时与连接池大小联动:当连接池较大(如 100+)时,适当缩短
idle_timeout(如 5 分钟),避免大量空闲连接占用内存。 - 健康检查失败断开后的重试保护:配置
retry_budget和panic_threshold,防止健康检查抖动导致的重试风暴。 - 避免对主动断开重试:在
retry_on配置中,不要包含connect-failure之外的主动断开相关条件。
案例:某电商平台在促销期间出现大量 503 错误。排查发现,Envoy 的
idle_timeout 设置为 10 秒,导致连接频繁断开重建。同时,健康检查间隔为 2 秒,上游短暂抖动时大量端点被剔除。优化方案:将 idle_timeout 调整为 5 分钟,健康检查间隔调整为 10 秒,并启用 panic_threshold: 50%。优化后 503 错误率从 8% 降至 0.3%。