5Gateway 重试 · SpringCloud微服务实战 · 看云

5. Retry GatewayFilter

导航

前面我们在将FeignRibbon的时候已经提到过重试机制,就是在我们发送Http 请求的时候希望一次失败后可以再尝试发送一次,因为前几次可能因为网络等不确定原因。Spring Cloud Gateway对请求重试提供的一个GatewayFilter Factory

本节代码地址


5.1 应用配置

server:
  port: 8711
spring:
  application:
    name: fw-gateways-gateway
  profiles:
    active: retry_route
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
---
spring:
  cloud:
    gateway:
      routes:
        - id: retry_route
          uri: lb://fw-cloud-ribbon-server
          predicates:
            - After=2020-01-08T18:30:11.965+08:00[Asia/Shanghai]
          filters:
          - name: Retry
            args:
              retries: 3
              series:
                - SERVER_ERROR
              statuses:
                - INTERNAL_SERVER_ERROR
                - BAD_GATEWAY
              methods:
                - GET
              exceptions:
                - java.io.IOException
                - java.util.concurrent.TimeoutException
  profiles: retry_route

Spring Cloud Gateway 通过以下参数来控制重试机制: 。

  • retries:重试次数,默认值是 3 次
  • statuses:HTTP 的状态返回码,取值请参考:org.springframework.http.HttpStatus
  • methods:指定哪些方法的请求需要进行重试逻辑,默认值是 GET 方法,取值参考:org.springframework.http.HttpMethod
  • series:一些列的状态码配置,取值参考:org.springframework.http.HttpStatus.Series。符合的某段状态码才会进行重试逻辑,默认值是 SERVER_ERROR,值是 5,也就是 5XX(5 开头的状态码),共有5 个值。
  • exceptions:应重试的引发异常的列表。
  • backoff:为重试配置的指数补偿。重试在的退避间隔后执行firstBackoff * (factor ^ n),其中n为迭代。如果maxBackoff已配置,则应用的最大退避限制为maxBackoff。如果basedOnPreviousValue为true,则使用计算退避prevBackoff * factor

5.2 源码分析

public static class RetryConfig implements HasRouteId {
    private String routeId;
    private int retries = 3;
    private List<Series> series;
    private List<HttpStatus> statuses;
    private List<HttpMethod> methods;
    private List<Class<? extends Throwable>> exceptions;
    private RetryGatewayFilterFactory.BackoffConfig backoff;

    public RetryConfig() {
        this.series = RetryGatewayFilterFactory.toList(Series.SERVER_ERROR);
        this.statuses = new ArrayList();
        this.methods = RetryGatewayFilterFactory.toList(HttpMethod.GET);
        this.exceptions = RetryGatewayFilterFactory.toList(IOException.class, TimeoutException.class);
    }
    ......

通过分析RetryConfig,我们可以看到重试支持的参数和默认值。

  • retries:重试次数,默认值是3次
  • series:状态码配置(分段),符合的某段状态码才会进行重试逻辑,默认值是SERVER_ERROR,值是5,也就是5XX(5开头的状态码),共有5个值:
public enum Series {
    INFORMATIONAL(1),
    SUCCESSFUL(2),
    REDIRECTION(3),
    CLIENT_ERROR(4),
    SERVER_ERROR(5);
}

  • statuses:状态码配置,和series不同的是这边是具体状态码的配置,取值请参考:org.springframework.http.HttpStatus
  • methods:指定哪些方法的请求需要进行重试逻辑,默认值是GET方法,取值如下:
public enum HttpMethod {
	GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
}

  • exceptions:指定哪些异常需要进行重试逻辑,默认值是IOException、TimeoutException

5.3 fw-cloud-ribbon-server 代码修改

修改user/{id}接口,随机抛出异常,导致接口重试。

int millis = new Random().nextInt(3000);
System.out.println("client线程休眠时间:"+millis);
Thread.sleep(millis);
if(millis>1000){
    throw new RuntimeException("error");
}

5.4 应用重启

9c84c91a6c66b93eae9401dc1855c571_MD5.png

浏览器或Postman 输入 localhost:8711/user/1
f2b49eec9e4d5c3bd6ab315db35c8afe_MD5.png

如果延迟时间超过1秒钟,就会抛异常,默认重试3次,3次之后仍然没有成功就会返回异常信息。