聊聊spring cloud的RetryableFeignLoadBalancer

本文主要研究一下spring cloud的RetryableFeignLoadBalancer

RetryableFeignLoadBalancer

spring-cloud-openfeign-core-2.2.0.M1-sources.jar!/org/springframework/cloud/openfeign/ribbon/RetryableFeignLoadBalancer.java

public class RetryableFeignLoadBalancer extends FeignLoadBalancer
		implements ServiceInstanceChooser {

	private final LoadBalancedRetryFactory loadBalancedRetryFactory;

	public RetryableFeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig,
			ServerIntrospector serverIntrospector,
			LoadBalancedRetryFactory loadBalancedRetryFactory) {
		super(lb, clientConfig, serverIntrospector);
		this.loadBalancedRetryFactory = loadBalancedRetryFactory;
		this.setRetryHandler(new DefaultLoadBalancerRetryHandler(clientConfig));
	}

	@Override
	public RibbonResponse execute(final RibbonRequest request,
			IClientConfig configOverride) throws IOException {
		final Request.Options options;
		if (configOverride != null) {
			RibbonProperties ribbon = RibbonProperties.from(configOverride);
			options = new Request.Options(ribbon.connectTimeout(this.connectTimeout),
					ribbon.readTimeout(this.readTimeout));
		}
		else {
			options = new Request.Options(this.connectTimeout, this.readTimeout);
		}
		final LoadBalancedRetryPolicy retryPolicy = this.loadBalancedRetryFactory
				.createRetryPolicy(this.getClientName(), this);
		RetryTemplate retryTemplate = new RetryTemplate();
		BackOffPolicy backOffPolicy = this.loadBalancedRetryFactory
				.createBackOffPolicy(this.getClientName());
		retryTemplate.setBackOffPolicy(
				backOffPolicy == null ? new NoBackOffPolicy() : backOffPolicy);
		RetryListener[] retryListeners = this.loadBalancedRetryFactory
				.createRetryListeners(this.getClientName());
		if (retryListeners != null && retryListeners.length != 0) {
			retryTemplate.setListeners(retryListeners);
		}
		retryTemplate.setRetryPolicy(retryPolicy == null ? new NeverRetryPolicy()
				: new FeignRetryPolicy(request.toHttpRequest(), retryPolicy, this,
						this.getClientName()));
		return retryTemplate.execute(new RetryCallback<RibbonResponse, IOException>() {
			@Override
			public RibbonResponse doWithRetry(RetryContext retryContext)
					throws IOException {
				Request feignRequest = null;
				// on retries the policy will choose the server and set it in the context
				// extract the server and update the request being made
				if (retryContext instanceof LoadBalancedRetryContext) {
					ServiceInstance service = ((LoadBalancedRetryContext) retryContext)
							.getServiceInstance();
					if (service != null) {
						feignRequest = ((RibbonRequest) request
								.replaceUri(reconstructURIWithServer(
										new Server(service.getHost(), service.getPort()),
										request.getUri()))).toRequest();
					}
				}
				if (feignRequest == null) {
					feignRequest = request.toRequest();
				}
				Response response = request.client().execute(feignRequest, options);
				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());
				}
				return new RibbonResponse(request.getUri(), response);
			}
		}, new LoadBalancedRecoveryCallback<RibbonResponse, Response>() {
			@Override
			protected RibbonResponse createResponse(Response response, URI uri) {
				return new RibbonResponse(uri, response);
			}
		});
	}

	@Override
	public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
			FeignLoadBalancer.RibbonRequest request, IClientConfig requestConfig) {
		return new RequestSpecificRetryHandler(false, false, this.getRetryHandler(),
				requestConfig);
	}

	@Override
	public ServiceInstance choose(String serviceId) {
		return new RibbonLoadBalancerClient.RibbonServer(serviceId,
				this.getLoadBalancer().chooseServer(serviceId));
	}

}
  • RetryableFeignLoadBalancer继承了FeignLoadBalancer,实现了ServiceInstanceChooser接口
  • 其构造器根据clientConfig创建了DefaultLoadBalancerRetryHandler;其choose方法使用的是getLoadBalancer().chooseServer,最后通过RibbonLoadBalancerClient.RibbonServer包装返回
  • 其execute方法首先创建了LoadBalancedRetryPolicy,进而创建retryTemplate,最后通过retryTemplate.execute来实现重试功能;其RetryCallback的doWithRetry方法在retryContext是LoadBalancedRetryContext的条件下会切换下一个service实例来进行重试

小结

RetryableFeignLoadBalancer继承了FeignLoadBalancer,对execute方法使用retryTemplate来实现重试,其中在retryContext是LoadBalancedRetryContext的条件下会切换下一个service实例来进行重试

doc

转载于:https://my.oschina.net/go4it/blog/3073845

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值