Spring-Cloud-Feign源码阅读(3)-FeignClient是如何调用的

一、Feign发起请求

        Feign在初始化时通过jdk动态代理完成了被调用方法与SynchronousMethodHandler的键值对映射(参考Spring-Cloud-Feign源码阅读(1)-FeignClient是如何初始化的),在调用方法时就会调用SynchronousMethodHandler的invoke方法。

final class SynchronousMethodHandler implements MethodHandler {
    ...
    public Object invoke(Object[] argv) throws Throwable {
        //完成feignClient解析之后,调用之前的实际参数的绑定
        RequestTemplate template = this.buildTemplateFromArgs.create(argv);
       
        while(true) {
            try {
                //执行请求并进行解码
                return this.executeAndDecode(template);
            } catch (RetryableException var8) {
                ...
            }
        }
    }
    
    ...
}
private static class BuildTemplateByResolvingArgs implements Factory {

        ...

        public RequestTemplate create(Object[] argv) {
            RequestTemplate mutable = RequestTemplate.from(this.metadata.template());
            if (this.metadata.urlIndex() != null) {
                int urlIndex = this.metadata.urlIndex();
                Util.checkArgument(argv[urlIndex] != null, "URI parameter %s was null", new Object[]{urlIndex});
                mutable.target(String.valueOf(argv[urlIndex]));
            }

            ...

            while(true) {

                   ...                   
 
                   if (this.metadata.queryMapIndex() != null) {
                       Object value = argv[this.metadata.queryMapIndex()];
                       Map<String, Object> queryMap = this.toQueryMap(value);
                       //传入QueryMap参数
                       template = this.addQueryMapQueryParameters(queryMap, template);
                   }

                   if (this.metadata.headerMapIndex() != null) {
                       //传入HeaderMap参数
                       template = this.addHeaderMapHeaders((Map)argv[this.metadata.headerMapIndex()], template);
                   }

                   return template;
                }
            }
        }
}
Object executeAndDecode(RequestTemplate template) throws Throwable {
        //此方法执行拦截器的apply方法
        Request request = this.targetRequest(template);

        ...        
   	
        try {
            //发起请求	
            response = this.client.execute(request, this.options);
        } catch (IOException var15) {
            if (this.logLevel != Level.NONE) {
                this.logger.logIOException(this.metadata.configKey(), this.logLevel, var15, this.elapsedTime(start));
            }

            throw FeignException.errorExecuting(request, var15);
        }

        long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
        boolean shouldClose = true;

        Object var10;
        try {

            //判断方法的返回类型  如果是Response.class,则不进行解码处理	
            if (Response.class == this.metadata.returnType()) {
                Response var18;
                if (response.body() == null) {
                    var18 = response;
                    return var18;
                }

                if (response.body().length() != null && (long)response.body().length() <= 8192L) {
                    byte[] bodyData = Util.toByteArray(response.body().asInputStream());
                    Response var20 = response.toBuilder().body(bodyData).build();
                    return var20;
                }

                shouldClose = false;
                var18 = response;
                return var18;
            }

            //如果http响应状态码是成功,则进行解码
            Object result;
            if (response.status() >= 200 && response.status() < 300) {
                if (Void.TYPE == this.metadata.returnType()) {
                    result = null;
                    return result;
                }

                result = this.decode(response);
                shouldClose = this.closeAfterDecode;
                var10 = result;
                return var10;
            }

            //如果http响应状态码非404情况下用errorDecoder解码	
            if (!this.decode404 || response.status() != 404 || Void.TYPE == this.metadata.returnType()) {
                throw this.errorDecoder.decode(this.metadata.configKey(), response);
            }

            result = this.decode(response);
            shouldClose = this.closeAfterDecode;
            var10 = result;
        } catch (IOException var16) {
            if (this.logLevel != Level.NONE) {
                this.logger.logIOException(this.metadata.configKey(), this.logLevel, var16, elapsedTime);
            }

            throw FeignException.errorReading(request, response, var16);
        } finally {
            if (shouldClose) {
                Util.ensureClosed(response.body());
            }

        }

        return var10;
    }

       

    Request targetRequest(RequestTemplate template) {
        Iterator var2 = this.requestInterceptors.iterator();

        while(var2.hasNext()) {
            RequestInterceptor interceptor = (RequestInterceptor)var2.next();
            interceptor.apply(template);
        }

        return this.target.apply(template);
    }

        feignClient方法在被调用之后,会执行到SynchronousMethodHandler的invoke方法,在绑定完实际参数之后,由LoadBalancerFeignClient发起请求,并根据返回类型进行解码。executeAndDecode之前的targetRequest会执行当前SynchronousMethodHandler的拦截器方法,但是在此处没有对拦截器进行排序,以初始化时List中的顺序为准。

  二、Feign的httpClient

        SynchronousMethodHandler的Object executeAndDecode(RequestTemplate template)方法里response = this.client.execute(request, this.options)发起请求,this.client默认情况下是LoadBalancerFeignClient,默认的httpClient是java.net.HttpURLConnection,也通过@Conditional系列注解实现了对org.apache.http.impl.client.CloseableHttpClient和okhttp3.OkHttpClient的支持。

@Configuration
class DefaultFeignLoadBalancedConfiguration {

	@Bean
	@ConditionalOnMissingBean
    //new Client.Default默认使用的java.net.HttpURLConnection
	public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
							  SpringClientFactory clientFactory) {
		return new LoadBalancerFeignClient(new Client.Default(null, null),
				cachingFactory, clientFactory);
	}
}
@ConditionalOnClass(ApacheHttpClient.class)
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
class HttpClientFeignLoadBalancedConfiguration {
    ...
    @Bean
	@ConditionalOnMissingBean(Client.class)
    //delegate是ApacheHttpClient
	public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
								  SpringClientFactory clientFactory, HttpClient httpClient)     
    {
		ApacheHttpClient delegate = new ApacheHttpClient(httpClient);
		return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
	}
}
@ConditionalOnClass(OkHttpClient.class)
@ConditionalOnProperty(value = "feign.okhttp.enabled")
class OkHttpFeignLoadBalancedConfiguration {
    ...
    @Bean
	@ConditionalOnMissingBean(Client.class)
    //delegate是OkHttpClient 
	public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
							  SpringClientFactory clientFactory, okhttp3.OkHttpClient okHttpClient) {
		OkHttpClient delegate = new OkHttpClient(okHttpClient);
		return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
	}
}
//Order is important here, last should be the default, first should be optional
// see https://github.com/spring-cloud/spring-cloud-netflix/issues/2086#issuecomment-316281653
@Import({ HttpClientFeignLoadBalancedConfiguration.class,
		OkHttpFeignLoadBalancedConfiguration.class,
		DefaultFeignLoadBalancedConfiguration.class })

        三个httpclient的顺序如上,如果相关依赖包都引入,配置也加上的话,优先CloseableHttpClient,其次OkHttpClient,最后就是HttpURLConnection。

  三、Feign集成Ribbon实现的客户端负载均衡

 (1)LoadBalancerFeignClient

package org.springframework.cloud.openfeign.ribbon;

/**
 * @author Dave Syer
 *
 */
public class LoadBalancerFeignClient implements Client {

	static final Request.Options DEFAULT_OPTIONS = new Request.Options();
    
    //实现Client接口的类,CloseableHttpClient、OkHttpClient、HttpURLConnection之一
	private final Client delegate;
    //构建FeignLoadBalancer的工厂
	private CachingSpringLoadBalancerFactory lbClientFactory;
    //ribbon的NamedContextFactory
	private SpringClientFactory clientFactory;

	@Override
	public Response execute(Request request, Request.Options options) throws IOException {
		try {
            //将url转换成asUri
			URI asUri = URI.create(request.url());
            //获取微服务名称
			String clientName = asUri.getHost();
            //去掉微服务名称后的uri
			URI uriWithoutHost = cleanUrl(request.url(), clientName);
			FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest(
					this.delegate, request, uriWithoutHost);
            //根据微服务名称获取相关的配置,这个对象很重要
			IClientConfig requestConfig = getClientConfig(options, clientName);
            //构建FeignLoadBalancer并发起调用
			return lbClient(clientName).executeWithLoadBalancer(ribbonRequest,
					requestConfig).toResponse();
		}
		catch (ClientException e) {
            ...
		}
	}
package org.springframework.cloud.openfeign.ribbon;

@Configuration
class DefaultFeignLoadBalancedConfiguration {
	@Bean
	@ConditionalOnMissingBean
	public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
							  SpringClientFactory clientFactory) {
		return new LoadBalancerFeignClient(new Client.Default(null, null),
				cachingFactory, clientFactory);
	}
}

(2)SpringClientFactory

package org.springframework.cloud.netflix.ribbon;

public class RibbonAutoConfiguration {

    @Bean
    public SpringClientFactory springClientFactory() {
        SpringClientFactory factory = new SpringClientFactory();
        factory.setConfigurations(this.configurations);
        return factory;
    }
}

(3)CachingSpringLoadBalancerFactory

        针对每个clientName都会生成一个FeignLoadBalancer对象,并缓存到内存。注入时也会根据@ConditionalOnClass注解判断是否具有重试的功能。

package org.springframework.cloud.openfeign.ribbon;

public class CachingSpringLoadBalancerFactory {

	protected final SpringClientFactory factory;
	protected LoadBalancedRetryFactory loadBalancedRetryFactory = null;

	private volatile Map<String, FeignLoadBalancer> cache = new ConcurrentReferenceHashMap<>();

    ...

    //构建FeignLoadBalancer对象
	public FeignLoadBalancer create(String clientName) {
		FeignLoadBalancer client = this.cache.get(clientName);
		if(client != null) {
			return client;
		}
        //获取ClientConfig  这个对象很重要
		IClientConfig config = this.factory.getClientConfig(clientName);
        //ILoadBalancer获取ribbon的负载均衡  这个对象很重要
		ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
		ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class);
        //判断是否有重试的工厂
		client = loadBalancedRetryFactory != null ? new RetryableFeignLoadBalancer(lb, config, serverIntrospector,
			loadBalancedRetryFactory) : new FeignLoadBalancer(lb, config, serverIntrospector);
		this.cache.put(clientName, client);
		return client;
	}

}
package org.springframework.cloud.openfeign.ribbon;

public class FeignRibbonClientAutoConfiguration {

	@Bean
	@Primary
	@ConditionalOnMissingBean
	@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
	public CachingSpringLoadBalancerFactory cachingLBClientFactory(
			SpringClientFactory factory) {
		return new CachingSpringLoadBalancerFactory(factory);
	}

	@Bean
	@Primary
	@ConditionalOnMissingBean
	@ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")
	public CachingSpringLoadBalancerFactory retryabeCachingLBClientFactory(
		SpringClientFactory factory,
		LoadBalancedRetryFactory retryFactory) {
		return new CachingSpringLoadBalancerFactory(factory, retryFactory);
	}
}

(4)FeignLoadBalancer

        仅有一个execute方法,executeWithLoadBalancer方法在其父类AbstractLoadBalancerAwareClient。

package org.springframework.cloud.openfeign.ribbon;

public class FeignLoadBalancer extends
		AbstractLoadBalancerAwareClient<FeignLoadBalancer.RibbonRequest, FeignLoadBalancer.RibbonResponse> {

	private final RibbonProperties ribbon;
	protected int connectTimeout;
	protected int readTimeout;
	protected IClientConfig clientConfig;
	protected ServerIntrospector serverIntrospector;

	@Override
	public RibbonResponse execute(RibbonRequest request, IClientConfig configOverride)
			throws IOException {
		Request.Options options;
		if (configOverride != null) {
			RibbonProperties override = RibbonProperties.from(configOverride);
			options = new Request.Options(
					override.connectTimeout(this.connectTimeout),
					override.readTimeout(this.readTimeout));
		}
		else {
			options = new Request.Options(this.connectTimeout, this.readTimeout);
		}
		Response response = request.client().execute(request.toRequest(), options);
		return new RibbonResponse(request.getUri(), response);
	}
}
package com.netflix.client;

public abstract class AbstractLoadBalancerAwareClient<S extends ClientRequest, T extends IResponse> extends LoadBalancerContext implements IClient<S, T>, IClientConfigAware {
    public AbstractLoadBalancerAwareClient(ILoadBalancer lb) {
        super(lb);
    }

    public T executeWithLoadBalancer(S request) throws ClientException {
        return this.executeWithLoadBalancer(request, (IClientConfig)null);
    }

    public T executeWithLoadBalancer(final S request, final IClientConfig requestConfig) throws ClientException {
        LoadBalancerCommand command = this.buildLoadBalancerCommand(request, requestConfig);

        try {
            //使用rxjava响应式编程,command.submit内部会进行客户端负载均衡选择出适合的Server再进行调用执行
            return (IResponse)command.submit(new ServerOperation<T>() {
                public Observable<T> call(Server server) {
                    URI finalUri = AbstractLoadBalancerAwareClient.this.reconstructURIWithServer(server, request.getUri());
                    ClientRequest requestForServer = request.replaceUri(finalUri);

                    try {
                        //调用子类的execute方法
                        return Observable.just(AbstractLoadBalancerAwareClient.this.execute(requestForServer, requestConfig));
                    } catch (Exception var5) {
                        return Observable.error(var5);
                    }
                }
            }).toBlocking().single();
        } catch (Exception var6) {
            ...
        }
    }
public class LoadBalancerCommand<T> {

    private final URI loadBalancerURI;
    private final Object loadBalancerKey;
    private final LoadBalancerContext loadBalancerContext;
    private final RetryHandler retryHandler;
    private volatile ExecutionInfo executionInfo;
    private final Server server;
    private final ExecutionContextListenerInvoker<?, T> listenerInvoker;

    private Observable<Server> selectServer() {
        return Observable.create(new OnSubscribe<Server>() {
            public void call(Subscriber<? super Server> next) {
                try {
                    Server server = LoadBalancerCommand.this.loadBalancerContext.getServerFromLoadBalancer(LoadBalancerCommand.this.loadBalancerURI, LoadBalancerCommand.this.loadBalancerKey);
                    next.onNext(server);
                    next.onCompleted();
                } catch (Exception var3) {
                    next.onError(var3);
                }

            }
        });
    }

    public Observable<T> submit(final ServerOperation<T> operation) {
        
        ...//这段代码真没看懂

        Observable<T> o = (this.server == null ? this.selectServer() : Observable.just(this.server)).concatMap(new Func1<Server, Observable<T>>() {
            public Observable<T> call(Server server) { 
                ...
            }
        });

}

        submit方法调用私有的selectServer(),再调用LoadBalancerContext的getServerFromLoadBalancer方法。

public class LoadBalancerContext implements IClientConfigAware {

    public Server getServerFromLoadBalancer(@Nullable URI original, @Nullable Object loadBalancerKey) throws ClientException {
        String host = null;
        int port = -1;
        if (original != null) {
            host = original.getHost();
        }

        if (original != null) {
            Pair<String, Integer> schemeAndPort = this.deriveSchemeAndPortFromPartialUri(original);
            port = (Integer)schemeAndPort.second();
        }

        ILoadBalancer lb = this.getLoadBalancer();
        if (host == null) {
            if (lb != null) {
                //调用ILoadBalancer的chooseServer方法
                Server svc = lb.chooseServer(loadBalancerKey);
                ...
            }
        }

    }

}

(5)ILoadBalancer的默认实例ZoneAwareLoadBalancer

package org.springframework.cloud.netflix.ribbon;

@Configuration
@EnableConfigurationProperties
@Import({HttpClientConfiguration.class, OkHttpRibbonConfiguration.class, RestClientRibbonConfiguration.class, HttpClientRibbonConfiguration.class})
public class RibbonClientConfiguration {

        @Bean
    @ConditionalOnMissingBean
    public ILoadBalancer ribbonLoadBalancer(IClientConfig config, ServerList<Server> serverList, ServerListFilter<Server> serverListFilter, IRule rule, IPing ping, ServerListUpdater serverListUpdater) {
        //没有特殊配置的话,实例化一个ZoneAwareLoadBalancer对象
        return (ILoadBalancer)(this.propertiesFactory.isSet(ILoadBalancer.class, this.name) ? (ILoadBalancer)this.propertiesFactory.get(ILoadBalancer.class, config, this.name) : new ZoneAwareLoadBalancer(config, rule, ping, serverList, serverListFilter, serverListUpdater));
    }

}
package com.netflix.loadbalancer;

public class BaseLoadBalancer extends AbstractLoadBalancer implements PrimeConnectionListener, IClientConfigAware {

    protected IRule rule;

    //所有server和上线的server存到内存里
    @Monitor(
        name = "LoadBalancer_AllServerList",
        type = DataSourceType.INFORMATIONAL
    )
    protected volatile List<Server> allServerList;
    @Monitor(
        name = "LoadBalancer_UpServerList",
        type = DataSourceType.INFORMATIONAL
    )
    protected volatile List<Server> upServerList;

    //新增servers的方法
    public void addServers(List<Server> newServers) {
    }

    public Server chooseServer(Object key) {
        if (this.counter == null) {
            this.counter = this.createCounter();
        }

        this.counter.increment();
        if (this.rule == null) {
            return null;
        } else {
            try {
                //在调用成员变量Irule的choose方法
                return this.rule.choose(key);
            } catch (Exception var3) {
                logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", new Object[]{this.name, key, var3});
                return null;
            }
        }
    }
}
public class DynamicServerListLoadBalancer<T extends Server> extends BaseLoadBalancer {

    protected final UpdateAction updateAction;

    public DynamicServerListLoadBalancer(IClientConfig clientConfig) {
        this.isSecure = false;
        this.useTunnel = false;
        this.serverListUpdateInProgress = new AtomicBoolean(false);

        class NamelessClass_1 implements UpdateAction {
            NamelessClass_1() {
            }

            public void doUpdate() {
                DynamicServerListLoadBalancer.this.updateListOfServers();
            }
        }
        
        //定义更新Action动账的匿名类
        this.updateAction = new NamelessClass_1();
        this.initWithNiwsConfig(clientConfig);
    }

    @VisibleForTesting
    public void updateListOfServers() {
        List<T> servers = new ArrayList();
        if (this.serverListImpl != null) {
            //根据微服务名称获取最新的Servers
            servers = this.serverListImpl.getUpdatedListOfServers();
            LOGGER.debug("List of Servers for {} obtained from Discovery client: {}", this.getIdentifier(), servers);
            if (this.filter != null) {
                servers = this.filter.getFilteredListOfServers((List)servers);
                LOGGER.debug("Filtered List of Servers for {} obtained from Discovery client: {}", this.getIdentifier(), servers);
            }
        }
        
        //更新Servers
        this.updateAllServerList((List)servers);
    }

    protected void updateAllServerList(List<T> ls) {
        //使用cas防止并发
        if (this.serverListUpdateInProgress.compareAndSet(false, true)) {
            try {
                Iterator var2 = ls.iterator();

                while(var2.hasNext()) {
                    T s = (Server)var2.next();
                    s.setAlive(true);
                }
                
                //重新设置ServersList
                this.setServersList(ls);
                super.forceQuickPing();
            } finally {
                this.serverListUpdateInProgress.set(false);
            }
        }

    }

    public void setServersList(List lsrv) {
        super.setServersList(lsrv);
        Map<String, List<Server>> serversInZones = new HashMap();
        Iterator var4 = lsrv.iterator();
        
        //将ServerList按照zone区分开
        while(var4.hasNext()) {
            Server server = (Server)var4.next();
            this.getLoadBalancerStats().getSingleServerStat(server);
            String zone = server.getZone();
            if (zone != null) {
                zone = zone.toLowerCase();
                List<Server> servers = (List)serversInZones.get(zone);
                if (servers == null) {
                    servers = new ArrayList();
                    serversInZones.put(zone, servers);
                }

                ((List)servers).add(server);
            }
        }
        
        //ZoneAwareLoadBalancer重写了该方法
        this.setServerListForZones(serversInZones);
    }

}
package com.netflix.loadbalancer;

public class ZoneAwareLoadBalancer<T extends Server> extends DynamicServerListLoadBalancer<T> {
        
        //重写父类的chooseServer
        public Server chooseServer(Object key) {
        if (ENABLED.get() && this.getLoadBalancerStats().getAvailableZones().size() > 1) {
            Server server = null;

            try {
                LoadBalancerStats lbStats = this.getLoadBalancerStats();
                Map<String, ZoneSnapshot> zoneSnapshot = ZoneAvoidanceRule.createSnapshot(lbStats);
                logger.debug("Zone snapshots: {}", zoneSnapshot);
                if (this.triggeringLoad == null) {
                    this.triggeringLoad = DynamicPropertyFactory.getInstance().getDoubleProperty("ZoneAwareNIWSDiscoveryLoadBalancer." + this.getName() + ".triggeringLoadPerServerThreshold", 0.2D);
                }

                if (this.triggeringBlackoutPercentage == null) {
                    this.triggeringBlackoutPercentage = DynamicPropertyFactory.getInstance().getDoubleProperty("ZoneAwareNIWSDiscoveryLoadBalancer." + this.getName() + ".avoidZoneWithBlackoutPercetage", 0.99999D);
                }

                Set<String> availableZones = ZoneAvoidanceRule.getAvailableZones(zoneSnapshot, this.triggeringLoad.get(), this.triggeringBlackoutPercentage.get());
                logger.debug("Available zones: {}", availableZones);
                if (availableZones != null && availableZones.size() < zoneSnapshot.keySet().size()) {
                    String zone = ZoneAvoidanceRule.randomChooseZone(zoneSnapshot, availableZones);
                    logger.debug("Zone chosen: {}", zone);
                    if (zone != null) {
                        //根据zone从map里获取BaseLoadBalancer,再调用BaseLoadBalancer的chooseServer方法
                        BaseLoadBalancer zoneLoadBalancer = this.getLoadBalancer(zone);
                        server = zoneLoadBalancer.chooseServer(key);
                    }
                }
            } catch (Exception var8) {
                logger.error("Error choosing server using zone aware logic for load balancer={}", this.name, var8);
            }

            if (server != null) {
                return server;
            } else {
                //如果筛选出的server是空则会调用父类的chooseServer方法
                logger.debug("Zone avoidance logic is not invoked.");
                return super.chooseServer(key);
            }
        } else {
            logger.debug("Zone aware logic disabled or there is only one zone");
            return super.chooseServer(key);
        }
    }

}

(6)IRule的默认实例ZoneAvoidanceRule

@Configuration
@EnableConfigurationProperties
@Import({HttpClientConfiguration.class, OkHttpRibbonConfiguration.class, RestClientRibbonConfiguration.class, HttpClientRibbonConfiguration.class})
public class RibbonClientConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public IRule ribbonRule(IClientConfig config) {
        if (this.propertiesFactory.isSet(IRule.class, this.name)) {
            return (IRule)this.propertiesFactory.get(IRule.class, config, this.name);
        } else {
            ZoneAvoidanceRule rule = new ZoneAvoidanceRule();
            rule.initWithNiwsConfig(config);
            return rule;
        }
    }
}
package com.netflix.loadbalancer;

public interface IRule {
    //选择一个server
    Server choose(Object var1);

    //设置一个ILoadBalancer  ILoadBalancer对象有serverList
    void setLoadBalancer(ILoadBalancer var1);

    ILoadBalancer getLoadBalancer();
}
package com.netflix.loadbalancer;

public abstract class AbstractLoadBalancerRule implements IRule, IClientConfigAware {
    private ILoadBalancer lb;

    public AbstractLoadBalancerRule() {
    }

    public void setLoadBalancer(ILoadBalancer lb) {
        this.lb = lb;
    }

    public ILoadBalancer getLoadBalancer() {
        return this.lb;
    }
}
package com.netflix.loadbalancer;

public abstract class PredicateBasedRule extends ClientConfigEnabledRoundRobinRule {
    public PredicateBasedRule() {
    }

    //抽象方法设置断言
    public abstract AbstractServerPredicate getPredicate();

    public Server choose(Object key) {
        //从ILoadBalancer获取所有的server
        ILoadBalancer lb = this.getLoadBalancer();
        //调用断言的chooseRoundRobinAfterFiltering 选择合适的Server
        Optional<Server> server = this.getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);
        return server.isPresent() ? (Server)server.get() : null;
    }
}
public class ZoneAvoidanceRule extends PredicateBasedRule {
    private static final Random random = new Random();
    private CompositePredicate compositePredicate;

    public ZoneAvoidanceRule() {
        ZoneAvoidancePredicate zonePredicate = new ZoneAvoidancePredicate(this);
        AvailabilityPredicate availabilityPredicate = new AvailabilityPredicate(this);
        //创建一个ZoneAvoidancePredicate 和 AvailabilityPredicate 组成的组合断言
        this.compositePredicate = this.createCompositePredicate(zonePredicate, availabilityPredicate);
    }

    public AbstractServerPredicate getPredicate() {
        return this.compositePredicate;
    }
}

(7)Predicate

package com.netflix.loadbalancer;

public abstract class AbstractServerPredicate implements Predicate<PredicateKey> {

        public List<Server> getEligibleServers(List<Server> servers, Object loadBalancerKey) {
        if (loadBalancerKey == null) {
            return ImmutableList.copyOf(Iterables.filter(servers, this.getServerOnlyPredicate()));
        } else {
            List<Server> results = Lists.newArrayList();
            Iterator var4 = servers.iterator();

            //通过断言的apply方法从所有的server筛选出合格的server
            while(var4.hasNext()) {
                Server server = (Server)var4.next();
                if (this.apply(new PredicateKey(loadBalancerKey, server))) {
                    results.add(server);
                }
            }

            return results;
        }
    }

        public Optional<Server> chooseRoundRobinAfterFiltering(List<Server> servers, Object loadBalancerKey) {
        //筛选出合格的server之后做一个轮询
        List<Server> eligible = this.getEligibleServers(servers, loadBalancerKey);
        return eligible.size() == 0 ? Optional.absent() : Optional.of(eligible.get(this.incrementAndGetModulo(eligible.size())));
    }
}
package com.netflix.loadbalancer;

public class CompositePredicate extends AbstractServerPredicate {
    
    //组合多个断言
    public static CompositePredicate.Builder withPredicates(AbstractServerPredicate... primaryPredicates) {
        return new CompositePredicate.Builder(primaryPredicates);
    }

    public static class Builder {
        private CompositePredicate toBuild = new CompositePredicate();

        Builder(AbstractServerPredicate primaryPredicate) {
            this.toBuild.delegate = primaryPredicate;
        }
        
        //多个断言之间是and关系
        Builder(AbstractServerPredicate... primaryPredicates) {
            Predicate<PredicateKey> chain = Predicates.and(primaryPredicates);
            this.toBuild.delegate = AbstractServerPredicate.ofKeyPredicate(chain);
        }
    }

    private static class AndPredicate<T> implements Predicate<T>, Serializable {
        private final List<? extends Predicate<? super T>> components;
        private static final long serialVersionUID = 0L;

        private AndPredicate(List<? extends Predicate<? super T>> components) {
            this.components = components;
        }
        
        //AndPredicate 多个断言都为true
        public boolean apply(@Nullable T t) {
            for(int i = 0; i < this.components.size(); ++i) {
                if (!((Predicate)this.components.get(i)).apply(t)) {
                    return false;
                }
            }

            return true;
        }
    }

}
package com.netflix.loadbalancer;


public class AvailabilityPredicate extends AbstractServerPredicate {

    public boolean apply(@Nullable PredicateKey input) {
        LoadBalancerStats stats = this.getLBStats();
        if (stats == null) {
            return true;
        } else {
            return !this.shouldSkipServer(stats.getSingleServerStat(input.getServer()));
        }
    }

    private boolean shouldSkipServer(ServerStats stats) {
        //判断server是否熔断或者超过了最大连接数限制
        return CIRCUIT_BREAKER_FILTERING.get() && stats.isCircuitBreakerTripped() || stats.getActiveRequestsCount() >= (Integer)this.activeConnectionsLimit.get();
    }

}
package com.netflix.loadbalancer;

public class ZoneAvoidancePredicate extends AbstractServerPredicate {

    private volatile DynamicDoubleProperty triggeringLoad = new DynamicDoubleProperty("ZoneAwareNIWSDiscoveryLoadBalancer.triggeringLoadPerServerThreshold", 0.2D);
    private volatile DynamicDoubleProperty triggeringBlackoutPercentage = new DynamicDoubleProperty("ZoneAwareNIWSDiscoveryLoadBalancer.avoidZoneWithBlackoutPercetage", 0.99999D);
    
    public boolean apply(@Nullable PredicateKey input) {
        //判断启用
        if (!ENABLED.get()) {
            return true;
        } else {
            String serverZone = input.getServer().getZone();
            if (serverZone == null) {
                return true;
            } else {
                LoadBalancerStats lbStats = this.getLBStats();
                if (lbStats == null) {
                    return true;
                } else if (lbStats.getAvailableZones().size() <= 1) {
                    return true;
                } else {
                    Map<String, ZoneSnapshot> zoneSnapshot = ZoneAvoidanceRule.createSnapshot(lbStats);
                    if (!zoneSnapshot.keySet().contains(serverZone)) {
                        return true;
                    } else {
                        logger.debug("Zone snapshots: {}", zoneSnapshot);
                        //根据triggeringLoad和triggeringBlackoutPercentage进行可用性判断,并避免不可用的服务
                        Set<String> availableZones = ZoneAvoidanceRule.getAvailableZones(zoneSnapshot, this.triggeringLoad.get(), this.triggeringBlackoutPercentage.get());
                        logger.debug("Available zones: {}", availableZones);
                        return availableZones != null ? availableZones.contains(input.getServer().getZone()) : false;
                    }
                }
            }
        }
    }

}

四、总结

feign在调用过程会分为以下步骤

(1)完成RequestTemplate的实参绑定。

(2)调用拦截器的RequestInterceptor方法,可以对RequestTemplate进行一些修改。

(3)进行负载均衡选择合适的server,由ILoadBalance提供serverList,由Predicate对serverList进行过滤,由IRule是选择server。对于几个关键的对象的关系如下

        ①针对每一个微服务,都会有一个FeignLoadBalancer对象,并且每个FeignLoadBalancer对象都有一个ZoneAwareLoadBalancer对象。

        ②ZoneAwareLoadBalancer继承了BaseloadBalancer,把ServerList存到内存里。每个ZoneAwareLoadBalancer对象通过ConcurrentHashMap的形式维护了不用的zone有不同的BaseloadBalancer,key为zone,value为BaseloadBalancer。并且ZoneAwareLoadBalancer继承了DynamicServerListLoadBalancer,会有一个线程每隔一段时间从注册中心获取最新的server,并按照zone更新到ZoneAwareLoadBalancer对象的ConcurrentHashMap内。ZoneAwareLoadBalancer重写了BaseloadBalancer的Server chooseServer(Object key),会根据zone从ConcurrentHashMap获取BaseloadBalancer再调用chooseServer方法,如果选择的Servr是空,则会调用父类的chooseServer,通过这种方式保证了相同zone的优先调用。BaseloadBalancer的chooseServer会调用成员变量IRule的choose方法。

        ③默认初始化的IRule的实例是ZoneAvoidanceRule实例。ZoneAvoidanceRule继承了PredicateBasedRule,会调用成员变量的AbstractServerPredicate的chooseRoundRobinAfterFiltering方法选择Server,就是调用Predicate的apply方法过滤掉一部分Server再进行轮询。ZoneAvoidanceRule组合了ZoneAvoidancePredicate和AvailabilityPredicate两个断言。

        ④AvailabilityPredicate会判断熔断以及最大连接数,ZoneAvoidancePredicate会根据triggeringLoad和triggeringBlackoutPercentage判断可用并进行zone的判断。

(4)发起http请求并根据状态码进行decode。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值