零、前言
网上找的各种方法,要么是老版本的,要么无效,经过一番源码研究,终于得出了配置方案。
软件版本:
Spring Boot 2.0.4.RELEASE
Spring Cloud Finchley SR2
一、原因
网上各种的方案,都是修改超时时间,当前版本修改超时时间有3中方案:
(1) feign client
#default为全局配置,如果要单独配置每个服务,改为服务名 #默认为10s feign.client.config.default.connectTimeout=10000 #默认为60s feign.client.config.default.readTimeout=60000
(2)hystrix
#默认为true可不配置 #hystrix.command.default.execution.timeout.enabled=true #默认为1s hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000
(3)rubbin
ribbon.ConnectTimeout=10000 ribbon.ReadTimeout=60000
这三种配置会以最小的超时时间来生效。
那么问题来了,我把这三个配置项都配置上去了,而且把值改大,服务仍然秒超时。
二、解决方案
查阅了各种资料后,发现 FeignClient的默认超时时间为10s,不会开启重试机制。
看见重点了吗,“不会开启重试机制”,没有重试,超时时间再长也没用,所以还得手动加上。
#这是默认的配置,单次请求最大时长是1s,默认重试5次 #所以如果使用默认配置,超时时间最长也就6s左右,如果要更长时间,则需要自定义了 feign.client.config.default.retryer=feign.Retryer.Default
Retryer默认配置的源码
public class Default implements Retryer { private final int maxAttempts; private final long period; private final long maxPeriod; int attempt; long sleptForMillis; 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; } // visible for testing; protected long currentTimeMillis() { return System.currentTimeMillis(); } 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; } /** * Calculates the time interval to a retry attempt. The interval increases exponentially * with each attempt, at a rate of nextInterval *= 1.5 (where 1.5 is the backoff factor), to the * maximum interval. * * @return time in nanoseconds from now until the next attempt. */ long nextMaxInterval() { long interval = (long) (period * Math.pow(1.5, attempt - 1)); return interval > maxPeriod ? maxPeriod : interval; } @Override public Retryer clone() { return new Default(period, maxPeriod, maxAttempts); } }
三、最终配置
feign.hystrix.enabled=true #feign.client.config.default.connectTimeout=10000 #feign.client.config.default.readTimeout=60000 feign.client.config.default.retryer=feign.Retryer.Default hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000