Retry GatewayFilter 工厂
Retry GatewayFilter 工厂支持以下参数:
retries:应尝试的重试次数。statuses:应该重试的 HTTP 状态码,使用org.springframework.http.HttpStatus表示。methods:应该重试的 HTTP 方法,使用org.springframework.http.HttpMethod表示。series:应该重试的状态码系列,使用org.springframework.http.HttpStatus.Series表示。exceptions:应该重试的抛出异常列表。backoff:为重试配置的指数退避(exponential backoff)。- 重试将在
firstBackoff * (factor ^ n)的退避间隔后执行,其中n是迭代次数。 - 如果配置了
maxBackoff,应用的最大退避时间将被限制为maxBackoff。 - 如果
basedOnPreviousValue为 true,则退避时间通过prevBackoff * factor计算。
- 重试将在
jitter:为重试配置的随机抖动(random jitter)。- 生成一个介于
[backoff - backoff*randomFactor, backoff + backoff*randomFactor]之间的退避时间。
- 生成一个介于
timeout:为重试配置的超时时间。
如果启用了 Retry 过滤器,默认配置如下:
retries:3 次series:5XX 系列methods:GET 方法exceptions:IOException和TimeoutExceptionbackoff:禁用jitter:禁用timeout:无限制
以下示例配置了一个 Retry GatewayFilter:
application.yml
spring:
cloud:
gateway:
routes:
- id: retry_test
uri: http://localhost:8080/flakey
predicates:
- Host=*.retry.com
filters:
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY
methods: GET,POST
backoff:
firstBackoff: 10ms
maxBackoff: 50ms
factor: 2
basedOnPreviousValue: false
jitter:
randomFactor: 0.5
timeout: 100ms注意
当 Retry 过滤器与 forward: 前缀的 URL 一起使用时,应仔细编写目标端点。 在发生错误的情况下,目标端点不应执行任何可能导致响应被发送到客户端并已提交(committed)的操作。 例如,如果目标端点是一个带注解的 Controller,则目标 Controller 方法不应返回带有错误状态码的 ResponseEntity。 相反,它应该抛出一个 Exception 或发出的错误信号(例如,通过 Mono.error(ex) 返回值),以便 Retry 过滤器可以捕获并处理重试。
注意
使用 Retry 过滤器时,它将重试紧随其后的所有过滤器。请确保位于 Retry 过滤器之后的过滤器在多次执行时结果符合预期(即它们应当是幂等的)。
警告
当对任何带有请求体(Body)的 HTTP 方法使用 Retry 过滤器时,请求体将被缓存,这可能会导致网关内存受限(OOM 风险)。 请求体缓存在由 ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR 定义的请求属性中。对象的类型是 org.springframework.core.io.buffer.DataBuffer。
可以使用简化的“快捷方式”表示法,仅指定 status 和 method。
以下两个示例是等效的:
application.yml
spring:
cloud:
gateway:
routes:
- id: retry_route
uri: https://example.org
filters:
- name: Retry
args:
retries: 3
statuses: INTERNAL_SERVER_ERROR
methods: GET
backoff:
firstBackoff: 10ms
maxBackoff: 50ms
factor: 2
basedOnPreviousValue: false
jitter:
randomFactor: 0.5
timeout: 100ms
- id: retryshortcut_route
uri: https://example.org
filters:
- Retry=3,INTERNAL_SERVER_ERROR,GET,10ms,50ms,2,false,0.5,100ms补充教学 —— 如何优雅地配置重试?
1. 什么是 Backoff(退避)? 如果服务器挂了,不要立即疯狂重试,否则可能会把它彻底压垮(雪崩效应)。 “退避”就是“歇一会儿再试”。
- Exponential Backoff(指数退避):越试越慢。第一次歇 10ms,第二次歇 20ms,第三次歇 40ms... 让服务器有喘息的机会。
2. 什么是 Jitter(抖动)? 如果 1000 个用户同时重试,并且都等待严格的 10ms,那么 10ms 后服务器会突然收到 1000 个请求,再次崩溃。 “抖动”就是加点随机数。比如在 5ms ~ 15ms 之间随机选一个时间重试,把流量错峰打开。
3. 内存爆炸警告 千万小心对 上传文件 或 大 Body 请求 配置重试。 Spring Cloud Gateway 为了能够重发请求,必须把 Request Body 缓存在内存里。如果你允许重试一个 100MB 的文件上传请求,内存立马就少 100MB。并发一高,网关直接 OOM(内存溢出)挂掉。
最佳实践:
- 只对 幂等 的请求(如 GET)开启重试。
- 对 POST/PUT 请求开启重试时要极其谨慎,确保业务逻辑支持重复提交,且 Payload 不大。
- 一定要配置
timeout,防止重试导致请求响应时间过长,拖死客户端。