SpringCloud重試retry是一個很贊的功能,能夠有效的處理單點故障的問題。主要功能是當請求一個服務的某個實例時,譬如你的User服務啟動了2個,它們都在eureka里注冊了,那么正常情況下當請求User服務時,ribbon默認會輪詢這兩個實例。此時如果其中一個實例故障了,發生了宕機或者超時等,如果沒有配置啟用重試retry策略,那么調用方就會得到錯誤信息或者超時無響應或者是熔斷返回的信息。我們希望的自然是一個故障了,會自動切換到另一個去訪問。
最簡單的方法就是retry。
需要先在pom.xml里加入
-
<dependency>
-
<groupId>org.springframework.retry</groupId>
-
<artifactId>spring-retry</artifactId>
-
</dependency>
ribbon、zuul、feign都可以配置各自的retry方式。
1 ribbon配置如下


-
-
-
RestTemplate restTemplate() {
-
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
-
httpRequestFactory.setReadTimeout( 5000);
-
httpRequestFactory.setConnectTimeout( 5000);
-
return new RestTemplate(httpRequestFactory);
-
}
2 zuul配置如下
zuul的重試比較簡單,不需要任何代碼,直接在yml里配置即可。
注意,配置時,ribbon開頭的在yml里是不給提示的,不要以為不提示就是沒效果,其實是可以用的。
這個ReadTimeout和ConnectTimeout區別是很大的,ConnectTimeout是指建立連接的時間,如果目標服務宕機或網絡故障,那么響應的就是ConnectTimeout,無法連接。而ReadTimeout則是連接建立后,等待目標服務返回響應的時間,譬如目標服務做了一個復雜操作導致耗時較長,那么會觸發ReadTimeout。
譬如zuul路由了/user路徑到user服務上,如果User1實例宕機了,那么配置了retry的zuul就會在重試MaxAutoRetries次數后,切換到另一個實例User2上。如果User2也故障了,那么返回404.
retryableStatusCodes里面有幾個錯誤碼,意思就是遇到哪些錯誤碼時觸發重試。默認是404,我多配了幾個,僅供參考。
3 feign配置如下
feign默認是通過自己包下的Retryer進行重試配置,默認是5次
-
import static java.util.concurrent.TimeUnit.SECONDS;
-
-
/**
-
* Cloned for each invocation to {@link Client#execute(Request, feign.Request.Options)}.
-
* Implementations may keep state to determine if retry operations should continue or not.
-
*/
-
public interface Retryer extends Cloneable {
-
-
/**
-
* if retry is permitted, return (possibly after sleeping). Otherwise propagate the exception.
-
*/
-
void continueOrPropagate(RetryableException e);
-
-
Retryer clone();
-
-
public static 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;
-
}
-
-
-
Retryer feignRetryer() {
-
return Retryer.NEVER_RETRY;
-
}
-
-
Request. Options requestOptions(ConfigurableEnvironment env){
-
int ribbonReadTimeout = env.getProperty("ribbon.ReadTimeout", int.class, 6000);
-
int ribbonConnectionTimeout = env.getProperty("ribbon.ConnectTimeout", int.class, 3000);
-
-
return new Request.Options(ribbonConnectionTimeout, ribbonReadTimeout);
-
}
