spring cloud kubernetes在pod模式下服务调用源码解析
Posted 水中加点糖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring cloud kubernetes在pod模式下服务调用源码解析相关的知识,希望对你有一定的参考价值。
之所以只看pod模式下的服务调用链路,是因为在service模式下不会走缓存,效率低,并且负载均衡模式不能由spring cloud框架所控制,不太灵活
需要关注的几个类:
DiscoveryClient
org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient
org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient#choose(java.lang.String, org.springframework.cloud.client.loadbalancer.Request)
public <T> ServiceInstance choose(String serviceId, Request<T> request)
ReactiveLoadBalancer<ServiceInstance> loadBalancer = this.loadBalancerClientFactory.getInstance(serviceId);
if (loadBalancer == null)
return null;
else
Response<ServiceInstance> loadBalancerResponse = (Response)Mono.from(loadBalancer.choose(request)).block();
return loadBalancerResponse == null ? null : (ServiceInstance)loadBalancerResponse.getServer();
org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory#getInstance
public ReactiveLoadBalancer<ServiceInstance> getInstance(String serviceId)
return (ReactiveLoadBalancer)this.getInstance(serviceId, ReactorServiceInstanceLoadBalancer.class);
feign调用
implements ReactorServiceInstanceLoadBalancer
feign调用时用的org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient中的execute方法调用的。
其中获取服务列表的代码为:ServiceInstance instance = loadBalancerClient.choose(serviceId, lbRequest);
也就是org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient#choose(java.lang.String, org.springframework.cloud.client.loadbalancer.Request)这个方法,其中用的此方法:
ReactiveLoadBalancer<ServiceInstance> loadBalancer = this.loadBalancerClientFactory.getInstance(serviceId);
其中的loadBalancerClientFactory字段是在BlockingLoadBalancerClient初始化时设置的。需要看一下loadBalancerClientFactory传入的地方。
也就是org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient类初始化时LoadBalancerClient注入进去的是哪个类。
这个类的属于commons的包里,看一下其中loadbalancer中关于初始化的地方。
代码在此处:
org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration#blockingLoadBalancerClient
@Bean
@ConditionalOnBean(LoadBalancerClientFactory.class)
@ConditionalOnMissingBean
public LoadBalancerClient blockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory)
return new BlockingLoadBalancerClient(loadBalancerClientFactory);
这里注入了一个LoadBalancerClientFactory,这经的注入代码在此处:org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration#loadBalancerClientFactory
@ConditionalOnMissingBean
@Bean
public LoadBalancerClientFactory loadBalancerClientFactory(LoadBalancerClientsProperties properties)
LoadBalancerClientFactory clientFactory = new LoadBalancerClientFactory(properties);
clientFactory.setConfigurations(this.configurations.getIfAvailable(Collections::emptyList));
return clientFactory;
这个factory的代码中的getInstance方法:
@Override
public ReactiveLoadBalancer<ServiceInstance> getInstance(String serviceId)
return getInstance(serviceId, ReactorServiceInstanceLoadBalancer.class);
获取的是ReactorServiceInstanceLoadBalancer.class
则需要找到ReactorServiceInstanceLoadBalancer的实现类:
org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientConfiguration#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);
其中用懒加载获取的ServiceInstanceListSupplier的bean。
那么如果是service模式下,其中的ServiceInstanceListSupplier的实现类为:org.springframework.cloud.kubernetes.client.loadbalancer.KubernetesClientServicesListSupplier,其初始化代码为:
@Bean
@ConditionalOnProperty(name = "spring.cloud.kubernetes.loadbalancer.mode", havingValue = "SERVICE")
KubernetesServicesListSupplier kubernetesServicesListSupplier(Environment environment, CoreV1Api coreV1Api,
KubernetesClientServiceInstanceMapper mapper, KubernetesDiscoveryProperties discoveryProperties,
KubernetesNamespaceProvider kubernetesNamespaceProvider)
return new KubernetesClientServicesListSupplier(environment, mapper, discoveryProperties, coreV1Api,
kubernetesNamespaceProvider);
如果是pod模式,则使用的默认的初始化代码:org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientConfiguration.ReactiveSupportConfiguration#discoveryClientServiceInstanceListSupplier
其代码为:
@Bean
@ConditionalOnBean(ReactiveDiscoveryClient.class)
@ConditionalOnMissingBean
@Conditional(DefaultConfigurationCondition.class)
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context)
return ServiceInstanceListSupplier.builder().withDiscoveryClient().withCaching().build(context);
其中withDiscoveryClient方法:
/**
* Sets a @link ReactiveDiscoveryClient-based
* @link DiscoveryClientServiceInstanceListSupplier as a base
* @link ServiceInstanceListSupplier in the hierarchy.
* @return the @link ServiceInstanceListSupplierBuilder object
*/
public ServiceInstanceListSupplierBuilder withDiscoveryClient()
if (baseCreator != null && LOG.isWarnEnabled())
LOG.warn("Overriding a previously set baseCreator with a ReactiveDiscoveryClient baseCreator.");
this.baseCreator = context ->
ReactiveDiscoveryClient discoveryClient = context.getBean(ReactiveDiscoveryClient.class);
return new DiscoveryClientServiceInstanceListSupplier(discoveryClient, context.getEnvironment());
;
return this;
其中ReactiveDiscoveryClient的bean为:
@Bean
@ConditionalOnMissingBean
public KubernetesInformerReactiveDiscoveryClient kubernetesReactiveDiscoveryClient(
KubernetesNamespaceProvider kubernetesNamespaceProvider, SharedInformerFactory sharedInformerFactory,
Lister<V1Service> serviceLister, Lister<V1Endpoints> endpointsLister,
SharedInformer<V1Service> serviceInformer, SharedInformer<V1Endpoints> endpointsInformer,
KubernetesDiscoveryProperties properties)
return new KubernetesInformerReactiveDiscoveryClient(kubernetesNamespaceProvider, sharedInformerFactory,
serviceLister, endpointsLister, serviceInformer, endpointsInformer, properties);
public class KubernetesInformerReactiveDiscoveryClient implements ReactiveDiscoveryClient
所以由此可以看出,k8s中pod模式下用的是KubernetesInformerReactiveDiscoveryClient。
所以如果想要到达k8s模式下的个性化定制,可以参考官方文档https://docs.spring.io/spring-cloud-commons/docs/current/reference/html/#hints-based-loadbalancing,
参考代码:
org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplierBuilder#withHints
以上是关于spring cloud kubernetes在pod模式下服务调用源码解析的主要内容,如果未能解决你的问题,请参考以下文章
正在使用 Kubernetes Spring Cloud 多个配置映射
部署 spring-cloud-kubernetes kubernetes-hello-world-example 失败
#yyds干货盘点#spring-cloud-kubernetes官方demo运行实战