Retry and timeout settings for feigninclient

  springcloud

Default value

Default maxAttempts value

/Users/xixicat/.m2/repository/io/github/openfeign/feign-core/9.3.1/feign-core-9.3.1-sources.jar! /feign/Retryer.java

public Default() {
      this(100, SECONDS.toMillis(1), 5);
    }

    public Default(long period, long maxPeriod, int maxAttempts) {
      this.period = period;
      this.maxPeriod = maxPeriod;
      this.maxAttempts = maxAttempts;
      this.attempt = 1;
    }

Retry logic

/Users/xixicat/.m2/repository/io/github/openfeign/feign-core/9.3.1/feign-core-9.3.1-sources.jar! /feign/Retryer.java

public void continueOrPropagate(RetryableException e) {
      if (attempt++ >= maxAttempts) {
        throw e;
      }

      long interval;
      if (e.retryAfter() != null) {
        interval = e.retryAfter().getTime() - currentTimeMillis();
        if (interval > maxPeriod) {
          interval = maxPeriod;
        }
        if (interval < 0) {
          return;
        }
      } else {
        interval = nextMaxInterval();
      }
      try {
        Thread.sleep(interval);
      } catch (InterruptedException ignored) {
        Thread.currentThread().interrupt();
      }
      sleptForMillis += interval;
    }

Here, the initial value of attampt is 1, i.e. the first request is counted up. first, the attempt >= maxAttempts judgment is executed, and then the attempt+++is executed. Therefore, setting maxAttempts to 2 means to retry once.
/Users/xixicat/.m2/repository/io/github/openfeign/feign-core/9.3.1/feign-core-9.3.1-sources.jar! /feign/SynchronousMethodHandler.java

@Override
  public Object invoke(Object[] argv) throws Throwable {
    RequestTemplate template = buildTemplateFromArgs.create(argv);
    Retryer retryer = this.retryer.clone();
    while (true) {
      try {
        return executeAndDecode(template);
      } catch (RetryableException e) {
        retryer.continueOrPropagate(e);
        if (logLevel != Logger.Level.NONE) {
          logger.logRetry(metadata.configKey(), logLevel);
        }
        continue;
      }
    }
  }

About++

    @Test
    public void testPlus(){
        int attempt = 1;
        int maxAttempts = 1;
        try{
            if(attempt++ == maxAttempts){
                throw new RuntimeException("EXCEED");
            }
        }finally {
            System.out.println(attempt);
        }
    }

Output

2

java.lang.RuntimeException: EXCEED

  at XXXTest.testPlus(XXXTest.java:50)

Default timeout

/Users/xixicat/.m2/repository/io/github/openfeign/feign-core/9.3.1/feign-core-9.3.1-sources.jar! /feign/Request.java

    public Options(int connectTimeoutMillis, int readTimeoutMillis) {
      this.connectTimeoutMillis = connectTimeoutMillis;
      this.readTimeoutMillis = readTimeoutMillis;
    }

    public Options() {
      this(10 * 1000, 60 * 1000);
    }

Parameter setting

Timeout settings

    @Bean
    Request.Options feignOptions() {
        return new Request.Options(/**connectTimeoutMillis**/1 * 1000, /** readTimeoutMillis **/1 * 1000);
    }

Retry configuration

    @Bean
    Retryer feignRetryer() {
        return Retryer.NEVER_RETRY;
    }

Response time

Default retry response time (1s connectTimeout,1s readTimeout)

Percentage of the requests served within a certain time (ms)
  50%   6718
  66%   7020
  75%   7371
  80%   8237
  90%   8404
  95%   8404
  98%   8404
  99%   8404
 100%   8404 (longest request)

Not retry (1s connectTimeout,1s readTimeout)

Percentage of the requests served within a certain time (ms)
  50%   1219
  66%   1230
  75%   1307
  80%   1485
  90%   1674
  95%   1674
  98%   1674
  99%   1674
 100%   1674 (longest request)

Not retry (5s connectTimeout,5s readTimeout)

Percentage of the requests served within a certain time (ms)
  50%   5561
  66%   5592
  75%   5653
  80%   5677
  90%   5778
  95%   5778
  98%   5778
  99%   5778
 100%   5778 (longest request)

Summary

Feign client’s default connectTimeout is 10s and readTimeout is 60. simply setting timeout may not work immediately, because the default retry is 5 times. therefore, if fail fast is expected, the parameters of timeout and retry need to be customized at the same time, and reverse proxy should be ensured. For example, nginx’s proxy_connect_timeout and proxy_read_timeout need to be larger than feign’s configuration to be effective. Otherwise, nginx’s 504 Gateway Time-out is still perceived by external users and cannot achieve the effect of fallback.

doc