feign客户端请求之LoadBalancerLifecycle生命周期

LoadBalancerLifecycle接口允许在load-balancing执行前后应执行的操作,我们可以借此入口获取微服务请求的真实请求URL;

一、LoadBalancerLifecycle接口源码
public interface LoadBalancerLifecycle<RC, RES, T> {

	/**
	 * 判定服务实例对象是否允许执行方法回调
	 */
	default boolean supports(Class requestContextClass, Class responseClass, Class serverTypeClass) {
		return true;
	}

	/**
	 * 在执行load-balancing之前(即获取真实服务实例url之前)的回调方法
	 */
	void onStart(Request<RC> request);

	/**
	 * 已经选择一个真实的服务实例之后,在执行请求之前的回调方法
	 */
	void onStartRequest(Request<RC> request, Response<T> lbResponse);

	/**
	 * 在load-balancing负载均衡真实服务请求之后执行
	 */
	void onComplete(CompletionContext<RES, T, RC> completionContext);

}
二、基于loadbalance请求服务有两个FeignBlockingLoadBalancerClient(不支持重试)、RetryableFeignBlockingLoadBalancerClient(支持重试)

我们先看下FeignBlockingLoadBalancerClient的源码:


public class FeignBlockingLoadBalancerClient implements Client {

	...

	@Override
	public Response execute(Request request, Request.Options options) throws IOException {
    //获取请求URL
		final URI originalUri = URI.create(request.url());
    //获取微服务实例ID
		String serviceId = originalUri.getHost();
		Assert.state(serviceId != null, "Request URI does not contain a valid hostname: " + originalUri);
    //获取配置命中值
		String hint = getHint(serviceId);
    //获取请求上线文对象
		DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(
				new RequestDataContext(buildRequestData(request), hint));
    //获取符合当前请求实例的生命周期管理对象
		Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator
				.getSupportedLifecycleProcessors(
						loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
						RequestDataContext.class, ResponseData.class, ServiceInstance.class);
    //调用生命 周期onStart回调方法
		supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest));
    //获取请求实例对应的微服务实例对象
		ServiceInstance instance = loadBalancerClient.choose(serviceId, lbRequest);
    //请求响应对象
		org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse = new DefaultResponse(
				instance);
    //如果请求实例不存在,则直接调用生命周期完成方法onComplete
		if (instance == null) {
			String message = "Load balancer does not contain an instance for the service " + serviceId;
			if (LOG.isWarnEnabled()) {
				LOG.warn(message);
			}
			supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
					.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
							CompletionContext.Status.DISCARD, lbRequest, lbResponse)));
			return Response.builder().request(request).status(HttpStatus.SERVICE_UNAVAILABLE.value())
					.body(message, StandardCharsets.UTF_8).build();
		}
    //获取实例请求的真实请求对象
		String reconstructedUrl = loadBalancerClient.reconstructURI(instance, originalUri).toString();
    //构建Request请求对象
		Request newRequest = buildRequest(request, reconstructedUrl);
    //执行真实请求
		return executeWithLoadBalancerLifecycleProcessing(delegate, options, newRequest, lbRequest, lbResponse,
				supportedLifecycleProcessors);
	}

	protected Request buildRequest(Request request, String reconstructedUrl) {
		return Request.create(request.httpMethod(), reconstructedUrl, request.headers(), request.body(),
				request.charset(), request.requestTemplate());
	}

	// Visible for Sleuth instrumentation
	public Client getDelegate() {
		return delegate;
	}
	// 获取配置命中值
	private String getHint(String serviceId) {
		String defaultHint = properties.getHint().getOrDefault("default", "default");
		String hintPropertyValue = properties.getHint().get(serviceId);
		return hintPropertyValue != null ? hintPropertyValue : defaultHint;
	}

}

executeWithLoadBalancerLifecycleProcessing请求方法:

	static Response executeWithLoadBalancerLifecycleProcessing(Client feignClient, Request.Options options,
			Request feignRequest, org.springframework.cloud.client.loadbalancer.Request lbRequest,
			org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse,
			Set<LoadBalancerLifecycle> supportedLifecycleProcessors, boolean loadBalanced) throws IOException {
    //在获取真实请求URL之后,在发送真实请求之前执行onStartRequest回调方法
		supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, lbResponse));
		try {
      //执行真实请求
			Response response = feignClient.execute(feignRequest, options);
			if (loadBalanced) {
        //执行声明周期回调方法onComplete
				supportedLifecycleProcessors.forEach(
						lifecycle -> lifecycle.onComplete(new CompletionContext<>(CompletionContext.Status.SUCCESS,
								lbRequest, lbResponse, buildResponseData(response))));
			}
			return response;
		}
		catch (Exception exception) {
			if (loadBalanced) {
        //执行声明周期回调方法onComplete
				supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(
						new CompletionContext<>(CompletionContext.Status.FAILED, exception, lbRequest, lbResponse)));
			}
			throw exception;
		}
	}

如果开启spring.cloud.loadbalancer.retry.enabled=true重试能力,则执行的是RetryableFeignBlockingLoadBalancerClient,其执行流程跟上述一致,不在做详细分析;

GitHub地址:https://github.com/mingyang66/spring-parent

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值