利益均沾-feign负载均衡流程

feign负载均衡实际是指ribbon的负载均衡,本文主要围绕feign如何在代码中调用ribbon流程进行解析。
上篇分析feign的加载流程以及如何执行,但是关于客户端如何执行还留有疑问。
这里以业务中常用的okHttp为例,

ConditionalOnClass({ ILoadBalancer.class, Feign.class })
@Configuration
@AutoConfigureBefore(FeignAutoConfiguration.class)
@EnableConfigurationProperties({ FeignHttpClientProperties.class })
@Import({ HttpClientFeignLoadBalancedConfiguration.class,
		OkHttpFeignLoadBalancedConfiguration.class,
		DefaultFeignLoadBalancedConfiguration.class })
public class FeignRibbonClientAutoConfiguration {
}

这里注意到FeignRibbonClientAutoConfiguration会比FeignAutoConfiguration提前加载,因为使用了okHttp,进入OkHttpFeignLoadBalancedConfiguration。

@Configuration
@ConditionalOnClass(OkHttpClient.class)
@ConditionalOnProperty("feign.okhttp.enabled")
class OkHttpFeignLoadBalancedConfiguration {

	@Bean
	@ConditionalOnMissingBean(Client.class)
	public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
			SpringClientFactory clientFactory, okhttp3.OkHttpClient okHttpClient) {
		OkHttpClient delegate = new OkHttpClient(okHttpClient);
		return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
	}
}

feignClient会包装原生的OkHttpClient,最后组装LoadBalancerFeignClient的对象,用于执行http请求。

调用LoadBalancerFeignClient的execute,省略掉参数配置,关键就如下一行代码。

public Response execute(Request request, Request.Options options) throws IOException {
		...
		return lbClient(clientName)
					.executeWithLoadBalancer(ribbonRequest, requestConfig).toResponse();
		...
	}

1. 获取负载均衡客户端

	private FeignLoadBalancer lbClient(String clientName) {
		// lbClientFactory是指CachingSpringLoadBalancerFactory 
		return this.lbClientFactory.create(clientName);
	}
public FeignLoadBalancer create(String clientName) {
		// 缓存中查找,缓存存在直接返回
		FeignLoadBalancer client = this.cache.get(clientName);
		if (client != null) {
			return client;
		}
		IClientConfig config = this.factory.getClientConfig(clientName);
		// 负载均衡实现
		ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
		ServerIntrospector serverIntrospector = this.factory.getInstance(clientName,
				ServerIntrospector.class);
		// 这里默认情况下是创建FeignLoadBalancer		
		client = this.loadBalancedRetryFactory != null
				? new RetryableFeignLoadBalancer(lb, config, serverIntrospector,
						this.loadBalancedRetryFactory)
				: new FeignLoadBalancer(lb, config, serverIntrospector);
		// 放入缓存		
		this.cache.put(clientName, client);
		return client;
	}

无论生成那种FeignLoadBalancer,这里都不影响负载均衡的使用。

2.executeWithLoadBalancer
executeWithLoadBalancer 主要逻辑分为两步:

  1. 根据负载策略获取对应的服务
  2. 向对应服务执行发起请求
    public T executeWithLoadBalancer(final S request, final IClientConfig requestConfig) throws ClientException {
        LoadBalancerCommand<T> command = buildLoadBalancerCommand(request, requestConfig);
        try {
        	// submit包含负载均衡的处理,内部执行的任务是具体的请求逻辑
            return command.submit(...); 
        ...
        
    }
 public Observable<T> submit(final ServerOperation<T> operation) {
        // selectServer这里调用处理负载
        Observable<T> o = (server == null ? selectServer() : Observable.just(server))
                ....
    }
    private Observable<Server> selectServer() {
        return Observable.create(new OnSubscribe<Server>() {
            @Override
            public void call(Subscriber<? super Server> next) {
                try {
                    Server server = loadBalancerContext.getServerFromLoadBalancer(loadBalancerURI, loadBalancerKey);   
                    next.onNext(server);
                    next.onCompleted();
                } 
                ...
            }
        });
    }
public Server getServerFromLoadBalancer(@Nullable URI original, @Nullable Object loadBalancerKey) throws ClientException {
        ...
        ILoadBalancer lb = getLoadBalancer();
        if (host == null) {
            if (lb != null){
            	// 执行具体的均衡策略,默认为轮询
                Server svc = lb.chooseServer(loadBalancerKey);
                ...
            }
            ...
        }
        ...      
}          
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值