spring cloud kubernetes在pod模式下服务调用源码解析_水中加点糖-CSDN博客

标签: | 发表时间:2021-12-01 07:34 | 作者:
出处:https://blog.csdn.net

之所以只看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>ServiceInstancechoose(StringserviceId,Request<T>request){ReactiveLoadBalancer<ServiceInstance>loadBalancer=this.loadBalancerClientFactory.getInstance(serviceId);if(loadBalancer==null){returnnull;}else{Response<ServiceInstance>loadBalancerResponse=(Response)Mono.from(loadBalancer.choose(request)).block();returnloadBalancerResponse==null?null:(ServiceInstance)loadBalancerResponse.getServer();}}

org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory#getInstance

      publicReactiveLoadBalancer<ServiceInstance>getInstance(StringserviceId){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] 推荐:

Spring Cloud Kubernetes指南

- -
当我们构建微服务解决方案时,SpringCloud和Kubernetes都是最佳解决方案,因为它们为解决最常见的挑战提供组件. 但是,如果我们决定选择Kubernetes作为我们的解决方案的主要容器管理器和部署平台,我们仍然可以主要通过SpringCloudKubernetes项目使用SpringCloud的有趣特性.

拥抱Kubernetes,再见了Spring Cloud - 简书

- -
相信很多开发者在熟悉微服务工作后,才发现:. 以为用 Spring Cloud 已经成功打造了微服务架构帝国,殊不知引入了 k8s 后,却和 Cloud Native 的生态发展脱轨. 从 2013 年的 Spring Boot. 2012年10月,Mike Youngstrom在Spring jira中创建了一个功能需求,要求在Spring框架中支持无容器Web应用程序体系结构.

spring cloud项目改造为spring-cloud-kubernetes项目_水中加点糖-CSDN博客

- -
(一)基础k8s yaml脚本发布. (二)helm+shell脚本优化大量冗余配置发布. (三)jenkins用户审核的流水化方式部署. (四)service mesh(istio)服务网格化发布. (五)istio对项目进行金丝雀部署. spring-cloud-kubernetes之开发环境搭建.

Spring Cloud 使用 Kubernetes 作为注册中心_HelloWood-CSDN博客

- -
Spring Cloud 可以使用 Kubernetes 作为注册中心,实现服务注册和发现. 创建两个应用,Consumer 和 Provider,Provider 提供一个 REST 接口供 Consumer 调用. 指定服务的名称,用于实现调用. 添加  @EnableDiscoveryClient启用服务发现.

部署微服务的时候,Spring Cloud 和 Kubernetes 哪个更好? - DockOne.io

- -
【编者的话】本文比较了当下最火热的两大微服务开发平台:Spring Cloud和Kubernetes的优缺点,并指出结合二者的优点来组合使用,将在微服务旅程上获得更大成功. 当我们需要部署微服务的时候,哪个更好. Spring Cloud还是Kubernetes. 答案是都可以,只是各自有其优势. Kubernetes都宣称自己是开发和运行微服务的最佳环境,但是它们的本质非常不一样,所追求的目标也不同.

大话 Spring Cloud

- - IT瘾-dev
研究了一段时间spring boot了准备向spirng cloud进发,公司架构和项目也全面拥抱了Spring Cloud. 在使用了一段时间后发现Spring Cloud从技术架构上降低了对大型系统构建的要求,使我们以非常低的成本(技术或者硬件)搭建一套高效、分布式、容错的平台,但Spring Cloud也不是没有缺点,小型独立的项目不适合使用.

Spring Cloud限流详解 | Spring Cloud|周立

- -
限流往往是一个绕不开的话题. 本文详细探讨在Spring Cloud中如何实现限流. Zuul上实现限流是个不错的选择,只需要编写一个过滤器就可以了,关键在于如何实现限流的算法. 常见的限流算法有漏桶算法以及令牌桶算法. https://www.cnblogs.com/LBSer/p/4083131.html,写得通俗易懂,你值得拥有,我就不拽文了.

spring-cloud-kubernetes的服务发现和轮询实战(含熔断)_程序员欣宸的博客-CSDN博客

- -
本文是《spring-cloud-kubernetes实战系列》的第四篇,主要内容是在kubernetes上部署两个应用:Web-Service和Account-Service,通过spring-cloud-kubernetes提供的注册发现能力,实现Web-Service调用Account-Service提供的http服务;.

使用istio对spring cloud kubernetes项目进行金丝雀发布_水中加点糖-CSDN博客_istio springcloud

- -
(一)基础k8s yaml脚本发布. (二)helm+shell脚本优化大量冗余配置发布. (三)jenkins用户审核的流水化方式部署. (四)service mesh(istio)服务网格化发布. (五)istio对项目进行金丝雀部署. spring-cloud-kubernetes之开发环境搭建.

spring cloud kubernetes在pod模式下服务调用源码解析_水中加点糖-CSDN博客

- -
之所以只看pod模式下的服务调用链路,是因为在service模式下不会走缓存,效率低,并且负载均衡模式不能由spring cloud框架所控制,不太灵活. feign调用时用的org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient中的execute方法调用的.