共计 5170 个字符,预计需要花费 13 分钟才能阅读完成。
当咱们在我的项目中调用本人实现的 Feignclient 负载平衡中如何起作用?请看下图:
图一
在图一中咱们能够发现,在 ConsumerController 中调用自定义的 DemoFeignClient 办法时,通过 spring 容器中对 DemoFeignclient 的代理类的调用最终通过 feign.SynchronousMethodHandler.invoke()->openfeign.loadbalancer.execute()->org.springframework.cloud.loadbalancer.blocking.client.FeignBlockingLoadBalancerClient.choose()->org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer.choose() 这样的调用链,最终执行 spring cloud loadbalaner 中的轮询负载均横策略!
然而,上图中的这些要害类是如何组合起来发挥作用呢?请咱们一起持续剖析!spring cloud 我的项目启动后,spring 容器解析并加载 LoadBalancerClientConfiguration.java 配置文件(如下图所示)
图二
而后将 ”reactorServiceInstanceLoadBalancer” 注册到 beanDefinitionMap 中。
而后会扫描咱们申明的 controller, 因为 conroller 中注入了 DemoFeignClient,因而 spring 容器会递归创立 DemoFeignClient,创立 DemoFiegnClient 过程中会通过 AbstractAutowireCapableBeanFactory.obtainFromSupplier() 注入 instanceSupplier 实例, 也就是 FeignClientFactoryBean 实例!
上面是 org.springframework.cloud.openfeign.FeignClientsRegistrar.registerFeignClient() 办法次要逻辑:
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata,
Map<String, Object> attributes) {
// 疏忽非核心代码片段
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(clazz, () -> {
// 设置 url
factoryBean.setUrl(getUrl(beanFactory, attributes));
// 设置门路
factoryBean.setPath(getPath(beanFactory, attributes));
//decode404 布尔值 factoryBean.setDecode404(Boolean.parseBoolean(String.valueOf(attributes.get("decode404"))));
Object fallback = attributes.get("fallback");
// 设置 fallback
if (fallback != null) {factoryBean.setFallback(fallback instanceof Class ? (Class<?>) fallback
: ClassUtils.resolveClassName(fallback.toString(), null));
}
// 设置 fallback 工厂类
Object fallbackFactory = attributes.get("fallbackFactory");
if (fallbackFactory != null) {factoryBean.setFallbackFactory(fallbackFactory instanceof Class ? (Class<?>) fallbackFactory
: ClassUtils.resolveClassName(fallbackFactory.toString(), null));
}
// 实例化咱们申明的 DemoClient
return factoryBean.getObject();});
}
这还没有完,org.springframework.cloud.openfeign.FeignClientFactoryBean.getObject() 中最终执行 loadBalance();在 loadBalance() 中实例化 FeignInvocationHandler;
在我的项目启动胜利之后,咱们调用 DemoFeignClient 中的办法时
图三
通过图三能够发现,形容 DemoFeignClient 的 RootBeanDefinition 的类中还有一个叫“instanceSupplier”的类型属性,它的值是“FeignClientsRegistrar$lambda”,那么这个类时什么时候被注入进来的呢?答案就是下面剖析我的项目启动过程中 spring 容器依据 RootBeanDefinition 对 DemoFeignClient 的形容,通过对 ”FeignClientsRegistrar$lambda” 的调用实现对 DemoFeignClient 实例的创立。
在实现创立 DemoFeignClient 实例后,咱们调用 org.springframework.cloud.openfeign.loadbalancer。FeignBlockingLoadBalancerClient.execute() 执行负载平衡策略时,执行到如下代码块
Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator
.getSupportedLifecycleProcessors(loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
RequestDataContext.class, ResponseData.class, ServiceInstance.class);
“loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class)” 逻辑会获取 LoadBalancer 实例,最终调用 LoadBalancerClientConfiguration.java 中的 reactorServiceInstanceLoadBalancer() 实现创立负载平衡实例逻辑
@Bean
@ConditionalOnMissingBean
public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
// 创立负载平衡实例,而且咱们发现默认的负载平衡实例是轮询负载平衡实例
return new RoundRobinLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
}
ok,截止到目前为止,咱们的负载平衡实例曾经创立实现!
这样一来,咱们通过 openfeign 进行近程调用时,通过下图的调用链
图四
FeignInvocationHandler.invoke()->SynchronousMethodHandler.invoke()->org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient.execute()->org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient.choose()->org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer.choose(), 这样的调用链最终依据 RoundRobinLoadBalancer.choose() 获取服务实例。
public Mono<Response<ServiceInstance>> choose(Request request) {
ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider
.getIfAvailable(NoopServiceInstanceListSupplier::new);
// 返回服务实例
return supplier.get(request).next()
.map(serviceInstances -> processInstanceResponse(supplier, serviceInstances));
}
拿到服务实例后,FeignBlockingLoadBalancerClient.execute() 中最终通过 LoadBalancerUtils.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, boolean useRawStatusCodes)
throws IOException {supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, lbResponse));
try {
// 通过 openfeign 调用,获取响应后果
Response response = feignClient.execute(feignRequest, options);
if (loadBalanced) {
supportedLifecycleProcessors.forEach(
lifecycle -> lifecycle.onComplete(new CompletionContext<>(CompletionContext.Status.SUCCESS,
lbRequest, lbResponse, buildResponseData(response, useRawStatusCodes))));
}
return response;
}
catch (Exception exception) {if (loadBalanced) {
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(new CompletionContext<>(CompletionContext.Status.FAILED, exception, lbRequest, lbResponse)));
}
throw exception;
}
}