DiscoveryClient的属性:
private final AtomicReference<Applications> localRegionApps = new AtomicReference<Applications>();
Feign是怎么在eureka获取信息之后,把name转换成url并做到负载均衡的?
public MethodHandler create(Target<?> target, MethodMetadata md, RequestTemplate.Factory buildTemplateFromArgs, Options options, Decoder decoder, ErrorDecoder errorDecoder) { return new SynchronousMethodHandler(target, client, retryer, requestInterceptors, logger, logLevel, md, buildTemplateFromArgs, options, decoder, errorDecoder, decode404); }
每个接口每一个抽象方法,都会有一个methodhandler对应,执行的时候执行这个真正的methodhandler的invoke方法,真正调用的是response = client.execute(request, options); 方法点进去是httpurlconnection发起请求了,注意这个时候封装的request,只是一个
clientname和粗糙url的组合,比如"order"+getOrder,也就是微服务名字+后缀url,距离真正的url,还要根据order去eureka里面找到对应的server地址,进行连接和负载均衡。
那么url的解析
LoadBalancerFeignClient.excute()方法中,return 一个lbClient(clientName),得到一个FeignLoadBalancer,在方法里,ILoadBalancer lb = this.factory.getLoadBalancer(clientName);这个方法是去eureka中
获取注册信息,比如server地址,访问次数,负载均衡相关的东西。
public FeignLoadBalancer create(String clientName) { if (this.cache.containsKey(clientName)) { return this.cache.get(clientName); }
//下面这几句都是非常关键的 IClientConfig config = this.factory.getClientConfig(clientName); ILoadBalancer lb = this.factory.getLoadBalancer(clientName); ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class); FeignLoadBalancer client = enableRetry ? new RetryableFeignLoadBalancer(lb, config, serverIntrospector, loadBalancedRetryPolicyFactory) : new FeignLoadBalancer(lb, config, serverIntrospector); this.cache.put(clientName, client); return client; }
public <C> C getInstance(String name, Class<C> type) { C instance = super.getInstance(name, type); if (instance != null) { return instance;//这里instance不是null,说明在工厂中已经有值,而且这时候的balanceloader中已经有server信息。具体怎么找到,还需要看一下 } IClientConfig config = getInstance(name, IClientConfig.class); return instantiateWithConfig(getContext(name), type, config); }