Spring Cloud升级之路 - Hoxton - 9. 对网关非 Get 请求的重试与优化
2023-10-19 02:15:13
前言
在之前的系列《Spring Cloud升级之路 - Hoxton - 5. 实现微服务调用重试》中,我们针对 OpenFeign 和 Spring Cloud Gateway 都设置了重试。
- Get请求:任何非200 响应码,任何异常,都会重试。
- 非 Get 请求:任何IOException,都会重试。
这里存在一些问题,例如,Get 请求出现IOException,也不会重试。本文详细介绍了如何对 Spring Cloud Gateway 进行优化和针对非Get 请求进行重试。
重试优化
-
去除日志干扰
日志对于我们开发及排查问题至关重要,特别对于网关来说,更是如此。但有些日志的干扰对我们来说并无多大意义,例如:2020-12-08 16:44:08.584 INFO 32338 --- [ Thread-7] c.netflix.zuul.web.ZuulController : Cannot find connection to API-A: java.io.IOException: Connection reset by peer
可以发现,这是因为 Zuul 未能从目标微服务获取响应,于是发起了重试,导致了大量的 Connection reset by peer 类型的日志。对于这些干扰性日志,我们可以通过以下方式去除:
logging: level: com.netflix.zuul: ERROR
-
设置最大重试次数
我们可以通过设置ribbon.maxAutoRetries
和ribbon.maxAutoRetriesNextServer
来限制最大重试次数,还可以针对 Get 请求和非 Get 请求,分别限制最大重试次数。如下所示:ribbon: maxAutoRetries: 1 # Get 请求最大重试次数 maxAutoRetriesNextServer: 2 # 非 Get 请求最大重试次数
-
设置重试间隔
我们可以通过设置ribbon.retryableStatusCodes
来设置重试间隔,例如,当返回状态码为 500 时,重试间隔为 1 秒,当返回状态码为 503 时,重试间隔为 2 秒,如下所示:ribbon: retryableStatusCodes: - 500:1000 # 当返回状态码为 500 时,重试间隔为 1 秒 - 503:2000 # 当返回状态码为 503 时,重试间隔为 2 秒
针对非 Get 请求的重试
在之前的版本中,针对非 Get 请求的重试只针对 IOException 进行了设置,这显然是不够的,例如,当目标微服务宕机时,请求也会失败,这时就需要进行重试。
我们可以通过以下步骤来实现针对非 Get 请求的重试:
- 实现 GatewayFilterFactory 接口
- 重写 apply 方法
- 使用 CircuitBreaker 来实现重试
@Component
public class RetryFilter implements GatewayFilterFactory {
private static final Logger log = LoggerFactory.getLogger(RetryFilter.class);
private Resilience4JCircuitBreakerFactory circuitBreakerFactory;
public RetryFilter(Resilience4JCircuitBreakerFactory circuitBreakerFactory) {
this.circuitBreakerFactory = circuitBreakerFactory;
}
@Override
public GatewayFilter apply(Config config) {
CircuitBreaker circuitBreaker = circuitBreakerFactory.create("retry");
return (exchange, chain) -> circuitBreaker.run(() -> {
try {
return chain.filter(exchange);
} catch (Exception e) {
log.error("请求失败,触发重试", e);
throw e;
}
});
}
@Override
public List<String> shortcutFieldOrder() {
return Collections.emptyList();
}
@Override
public Class<Config> getConfigClass() {
return Config.class;
}
public static class Config {
}
}
在 apply
方法中,我们使用了 CircuitBreaker 来实现重试,当请求失败时,CircuitBreaker 会触发重试。
总结
本文详细介绍了如何对 Spring Cloud Gateway 进行优化和针对非Get 请求进行重试,希望能对大家有所帮助。