Spring Cloud Feign重試機制

Spring Cloud Feign重試機制

Feign組件默認使用Ribbon的重試機制並增長了根據狀態碼判斷重試機制,默認狀況下是不啓用的。Feign使用的是Spring Retry組件,須要引入依賴才能啓用。git

一、POM引入Spring Retry

<dependency>
        <groupId>org.springframework.retry</groupId>
        <artifactId>spring-retry</artifactId>
  </dependency>

二、配置文件

eureka-client:
   ribbon:
      MaxAutoRetries: 1
      MaxAutoRetriesNextServer: 1
      retryableStatusCodes: 500,404 
      OkToRetryOnAllOperations: true 
      NFLoadBalancerRuleClassName: com.netflix.loadbalancer.AvailabilityFilteringRule #負載均衡規則

eureka-client 是本身的serverId,MaxAutoRetries同一臺服務器上的最大重試次數(不包括第一次嘗試),MaxAutoRetriesNextServer要重試的下一個服務器的最大數量(不包括第一個服務器),retryableStatusCodes能夠根據接口返回的狀態碼判斷是否重試其餘服務,OkToRetryOnAllOperations只對全部的超時請求重試github

注意: Ribbon的重試機制只有對GET請求或者設置了OkToRetryOnAllOperations生效 詳情請查看源碼:spring

public class RibbonLoadBalancedRetryPolicy implements LoadBalancedRetryPolicy {
...
	public boolean canRetry(LoadBalancedRetryContext context) {
		HttpMethod method = context.getRequest().getMethod();
		return HttpMethod.GET == method || lbContext.isOkToRetryOnAllOperations();
	}
...
}

Feign對返回狀態碼作了重試判斷RetryableFeignLoadBalancerjson

public class RetryableFeignLoadBalancer extends FeignLoadBalancer
	implements ServiceInstanceChooser {
	...
	[@Override](https://my.oschina.net/u/1162528)
	public RibbonResponse execute(final RibbonRequest request,
			IClientConfig configOverride) throws IOException {
	...
		if (retryPolicy != null
						&& retryPolicy.retryableStatusCode(response.status())) {
					byte[] byteArray = response.body() == null ? new byte[] {}
							: StreamUtils
									.copyToByteArray(response.body().asInputStream());
					response.close();
					throw new RibbonResponseStatusCodeException(
							RetryableFeignLoadBalancer.this.clientName, response,
							byteArray, request.getUri());
		}
	...
	}
	...
}

重試機制用的是Spring Retry組件當拋出異常時進行重試!服務器

GET請求指的是feign client 請求其餘client時聲明的那個interface中mapping註解類型,RequestMapping不設置method默認爲GET請求app

@FeignClient("stores")
public interface StoreClient {
    @RequestMapping(method = RequestMethod.GET, value = "/stores")
    List<Store> getStores();

    @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
    Store update(@PathVariable("storeId") Long storeId, Store store);
}
相關文章
相關標籤/搜索