请求重试
Nantian Gateway 可以自动重试发送到后端服务的失败请求。重试能够在无需调用方介入的情况下消除瞬时错误:连接被拒绝、后端返回 503、请求超时等情况。网关在数据平面内处理重试逻辑,因此你的客户端只需发送一次请求,收到一次响应。
网关何时进行重试
Section titled “网关何时进行重试”网关在满足两个条件时决定重试:
-
请求方法是可重放的。 GET、HEAD、OPTIONS、TRACE、PUT 和 DELETE 被视为可以安全重试。POST、PATCH 和 CONNECT 不会自动重试,因为它们可能有副作用。
-
响应状态码或传输错误匹配可重试的条件。 网关检查路由上附加的重试策略。策略将特定的 HTTP 状态码声明为可重试的。即使没有显式策略,网关也会在以下连接级传输错误时重试:连接被拒绝、主机无路由、连接超时。
当两个条件都满足且重试预算仍有容量时,网关会重置后端选择,释放之前的断路器许可,然后如同新请求一样重新派发请求。重试尝试计数器递增,如果配置了退避时长,网关会在发送重试请求前暂停。
重试策略配置
Section titled “重试策略配置”重试策略通过所选后端配置以按路由的方式设置,而不是通过独立的 CRD。策略指定三个字段:
| 字段 | 类型 | 说明 |
|---|---|---|
codes | 整数列表 | 触发重试的 HTTP 状态码。常用值:500、502、503、504。 |
attempts | 整数 | 最大重试次数。0 表示使用默认路由重试上限。 |
backoff | 时长 | 每次重试前可选的等待时间。若为 None,重试会立即执行。 |
当 attempts 为 0 或不存在显式策略时,默认重试上限为 DEFAULT_HTTP_ROUTE_RETRIES。传输级重试(没有路由策略时的连接失败)使用 DEFAULT_TRANSPORT_CONNECT_RETRIES,这是一个较小的固定数值。
示例:带退避的 5xx 重试
Section titled “示例:带退避的 5xx 重试”一个路由配置为在 5xx 响应时最多重试 3 次,每次重试之间间隔 500 毫秒:
# 概念示意:重试设置是路由后端配置的一部分retry: codes: - 500 - 502 - 503 - 504 attempts: 3 backoff: 500ms使用此配置,从后端收到 502 的请求会最多重试 3 次。网关在第一次重试前等待 500ms,第二次重试前等待 500ms,第三次重试前等待 500ms。如果所有重试都失败,网关将最后一个响应返回给客户端。退避是固定间隔的;Nantian Gateway 目前不在重试策略本身中实现抖动或指数退避。建议结合断路器限制来约束最坏情况下的延迟。
示例:无显式策略时的传输重试
Section titled “示例:无显式策略时的传输重试”如果路由上没有配置重试策略,网关仍会重试传输错误。连接被拒绝、无路由或连接超时会在无退避的情况下触发最多 DEFAULT_TRANSPORT_CONNECT_RETRIES 次重试。失败的端点会被标记为排除,以便后续重试时尝试不同的端点。
为防止重试风暴压垮后端,Nantian Gateway 强制执行重试预算。预算作为重试尝试的全局闸门。当预算耗尽时,即使按路由策略应该重试,网关也会停止重试。
重试预算控制器跟踪总请求数与成功重试数的比例。如果有过多重试正在失败,预算会收紧以保护后端容量。这种自动断路器机制确保重试行为在负载下优雅降级,而不是放大问题。
一次重试需要满足两个条件才能继续:按路由策略必须允许再次尝试,并且全局重试预算必须有可用的令牌。如果任一检查失败,就不执行重试,请求以当时的状态结束。
与断路器的交互
Section titled “与断路器的交互”每次重试尝试都会为后端申请一个新的断路器许可。这有两个实际影响:
-
一个后端配置了
maxInflightRequests: 10,路由配置了attempts: 3,最多可同时有 40 个正在处理的请求:10 个初始请求,每个请求最多 3 个正在执行的重试。断路器不会重复计数;每次尝试独立完成申请/释放周期。上一个许可在重试获取新许可之前释放。 -
当后端已达到断路器限制且重试需要许可时,重试会立即被拒绝,返回 503 并带有
CircuitBreakerOpen代理错误标志。请求在此刻失败,不再进行进一步重试。
传输重试成功后,网关会将失败的端点从传输排除列表中清除。这确保重试不会在后续请求中固定到已知故障的端点。
需要注意的是,首个请求如果是可重试的,也会为重试预算播下种子。这意味着一个最终无需重试就成功的可重试请求,仍然会影响预算对需求的评估。
重试与流式传输的交互
Section titled “重试与流式传输的交互”重试不适用于流式响应。网关在重试期间会缓冲响应数据,以便在重试成功后在线路上重放响应,但此缓冲区有固定容量限制。如果响应在重试周期完成前超出了重试缓冲区容量,则该请求的重试会被禁用,响应将在无重试保护的情况下流式传输。
在重试期间下游连接关闭的处理方式不同:如果下游客户端在网关为其执行重试时断开连接,重试将被放弃,上游连接也会关闭。
网关在请求上下文中跟踪重试状态。你可以通过访问日志和分布式追踪进行观察:
retryAttempts在每次重试时递增,当请求不带有重试上下文到达时重置为 0。retryBackoff保存配置的退避时长,在请求生命周期中可见。- 成功的重试会从上一次尝试产生
200级别的最终状态码。 - 耗尽所有重试的请求返回最后收到的状态码:如果所有后端都返回 502 则返回 502,如果每次尝试都超时则返回 504。
- 如果客户端在重试周期中断开连接,会出现代理错误标志
DC(下游关闭)。
重试预算控制器还导出内部指标。请将这些指标与断路器和上游健康指标结合使用,以了解重试是在弥补瞬时故障还是掩盖了更深层的容量问题。
生产环境注意事项
Section titled “生产环境注意事项”- 从少量尝试(2 或 3 次)和较保守的重试状态码(500、502、503)开始。过宽的重试窗口可能掩盖真正的应用 bug。
- 将重试与断路器配合使用。没有断路器的情况下,对已降级后端的重试可能将小规模性能下降扩大为全面中断。
- 幂等的 GET 端点是最安全的重试候选对象。在变更端点上启用重试之前,请验证 PUT 和 DELETE 的幂等性。
- 重试缓冲区容量限制了流式传输的重试。对于长连接的流式传输,应在客户端设计重试逻辑。