LoadBalancerClient

LoadBalancerAutoConfiguration負(fù)載均衡自動配置里面用于傳入負(fù)載均衡攔截器LoadBalancerInterceptor

spring 接口
package org.springframework.cloud.client.loadbalancer;

/**
 * Represents a client side load balancer
 * @author Spencer Gibb
 */
public interface LoadBalancerClient {

    ServiceInstance choose(String serviceId);

    <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;

    URI reconstructURI(ServiceInstance instance, URI original);

}

一共就3個(gè)方法,

  • 選擇 選擇具體一個(gè)服務(wù)實(shí)例
  • 執(zhí)行 執(zhí)行請求
  • 重新構(gòu)造url 把url中原來寫的服務(wù)名 換掉 換成實(shí)際的

只有 一實(shí)現(xiàn)類RibbonLoadBalancerClient 看里面的reconstructURI方法

/
 * @param instance 被選中的服務(wù)實(shí)例
     * @param original 原來寫的url 里面直接寫的服務(wù)名
     * @return 服務(wù)名替換掉的 實(shí)際url
     */
@Override
    public URI reconstructURI(ServiceInstance instance, URI original) {
        Assert.notNull(instance, "instance can not be null");
        
        String serviceId = instance.getServiceId();
        
        //clientFactory是 創(chuàng)造 負(fù)載均衡器 的工廠
        RibbonLoadBalancerContext context = this.clientFactory
        //每個(gè)ribbon客戶端 都會給生成一個(gè) spring上下文
                .getLoadBalancerContext(serviceId);
        
        //被選中的傳入的服務(wù)實(shí)例 轉(zhuǎn)成RibbonLoadBalancerContext需要的Server
        Server server = new Server(instance.getHost(), instance.getPort());
        boolean secure = isSecure(server, serviceId);
        URI uri = original;
        if (secure) {
            uri = UriComponentsBuilder.fromUri(uri).scheme("https").build().toUri();
        }
        //最終讓全部交給RibbonLoadBalancerContext來干
        return context.reconstructURIWithServer(server, uri);
    }

RibbonLoadBalancerClientexecute 方法

    @Override
    public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
        ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
        //按一定策略選中具體的服務(wù)實(shí)例
        Server server = getServer(loadBalancer);
        if (server == null) {
            throw new IllegalStateException("No instances available for " + serviceId);
        }
        //服務(wù)實(shí)例包裝一下 加入其他信息
        RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,
                serviceId), serverIntrospector(serviceId).getMetadata(server));

        RibbonLoadBalancerContext context = this.clientFactory
                .getLoadBalancerContext(serviceId);

//用來對服務(wù)的請求做跟蹤記錄的
        RibbonStatsRecorder statsRecorder = new RibbonStatsRecorder(context, server);

        try {
            //向這個(gè)具體的服務(wù)實(shí)例發(fā)起請求
            //apply方法接受一個(gè)ServiceInstance 是對一個(gè)服務(wù)實(shí)例的抽象定義,
//RibbonServer是對他的一個(gè)實(shí)現(xiàn)
            T returnVal = request.apply(ribbonServer);
            statsRecorder.recordStats(returnVal);
            return returnVal;
        }
        // catch IOException and rethrow so RestTemplate behaves correctly
        catch (IOException ex) {
            statsRecorder.recordStats(ex);
            throw ex;
        }
        catch (Exception ex) {
            statsRecorder.recordStats(ex);
            ReflectionUtils.rethrowRuntimeException(ex);
        }
        return null;
    }

首先就是 用serviceId得具體服務(wù)實(shí)例,怎么選擇的由ILoadBalancer決定,這是Betflix Ribbon的接口 里面有個(gè)chooseServer方法

任何包裝下Server 變?yōu)?RibbonServer 傳入LoadBalancerRequest.apply(ServiceInstance instance) 發(fā)送請求

apply是定義在LoadBalancerInterceptor里面的匿名類的

@Override
public ClientHttpResponse apply(final ServiceInstance instance)throws Exception {

//ServiceRequestWrapper 是內(nèi)部類  見下面    getURI()方法被重寫了 
    HttpRequest serviceRequest = new ServiceRequestWrapper(request,instance);
    
    //里面會調(diào)用這里被重寫的getURI()
    return execution.execute(serviceRequest, body);
}

private class ServiceRequestWrapper extends HttpRequestWrapper {

        private final ServiceInstance instance;

        public ServiceRequestWrapper(HttpRequest request, ServiceInstance instance) {
            super(request);
            this.instance = instance;
        }

        //這個(gè)方法被重寫   用的是loadBalancer 也就是RibbonLoadBalancerClient 里面根據(jù)傳入的服務(wù)實(shí)例改寫原來的url
        @Override
        public URI getURI() {
            URI uri = LoadBalancerInterceptor.this.
            //之前說過的 reconstructURI 組織具體請求的服務(wù)器實(shí)例地址
            loadBalancer.reconstructURI(this.instance, getRequest().getURI());
            return uri;
        }

    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容