1、Ribbon相关组件初始化 - Ribbon 核心原理与源码分析

我们举例说明Ribbon的作用,微服务架构中,服务B的一个功能依赖服务A,而服务A部署了多台机器,如下图

在这里插入图片描述

当一个请求来请求服务B时,服务B依赖Ribbon采用某种负载均衡的策略来调用服务A,Ribbon 在这里充当了负载均衡器的角色。

如何将服务A看做服务的提供方(服务端),那么Ribbon所处的服务B则是客户端,所以 Ribbon 称为客户端负载均衡器。

1、Ribbon 组件

1.1、Ribbon自动配置类

我们通过下图来了解一下 Ribbon 的各个组件

Spring IoC 实例化Ribbon的各个组件
在这里插入图片描述

这些组件通过 @Bean 定义在下面两个自动配置类中
spring-cloud-commons-1.3.3.RELEASE.jar 的 spring.factories 文件中设置了自动配置类
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration
spring-cloud-netflix-core-1.4.4.RELEASE.jar 的 spring.factories 文件中设置了自动配置类
org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration

(1)、LoadBalancerAutoConfiguration

@LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();

@Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializer(
		final List<RestTemplateCustomizer> customizers) {
	return new SmartInitializingSingleton() {
		public void afterSingletonsInstantiated() {
			for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
				for (RestTemplateCustomizer customizer : customizers) {
					customizer.customize(restTemplate);
				}
			}
		}
	};
}
@Configuration
static class LoadBalancerInterceptorConfig {	
	@Bean
	@ConditionalOnMissingBean
	public RestTemplateCustomizer restTemplateCustomizer(
			final LoadBalancerInterceptor loadBalancerInterceptor) {
		return new RestTemplateCustomizer() {
			@Override
			public void customize(RestTemplate restTemplate) {
				List<ClientHttpRequestInterceptor> list = new ArrayList<>(
						restTemplate.getInterceptors());
				list.add(loadBalancerInterceptor);
				restTemplate.setInterceptors(list);
			}
		};
	}
	@Bean
	public LoadBalancerInterceptor ribbonInterceptor(
			LoadBalancerClient loadBalancerClient,
			LoadBalancerRequestFactory requestFactory) {
		return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
	}
	@Bean
	@ConditionalOnMissingBean
	public LoadBalancerRequestFactory loadBalancerRequestFactory(
			LoadBalancerClient loadBalancerClient) {
		return new LoadBalancerRequestFactory(loadBalancerClient, transformers);
	}
}

(2)、RibbonAutoConfiguration

~ 为Ribbon 的自动配置类,配置了几个Bean

@Bean
@ConditionalOnMissingBean(LoadBalancerClient.class)
public LoadBalancerClient loadBalancerClient() {
	return new RibbonLoadBalancerClient(springClientFactory());
}

1.2、创建Bean实例

❓ //TODO
简单说一下采用工厂方法创建Bean的过程,首先IoC容器在启动初期会扫描所有的配置,后期会根据配置来实例化Bean,在实例化工厂方法定义的Bean时,首先会去查找工厂方法参数列表中的Bean,没有则会去创建Bean(前提是IoC容器中配置了该Bean)。

IOC容器实例化Ribbon相关的Bean大家回头看看上图,方便起见我把图复制到下方

Spring IoC 实例化Ribbon的各个组件
在这里插入图片描述

在容器初始化阶段(refresh->finishBeanFactoryInitialization)会进一步调用容器中所有 SmartInitializingSingleton 实例的 afterSingletonsInstantiated 方法,对照上面的源码和下图,体会一下容器是如何完善各个组件之间关联关系的。

IOC容器进一步创建Ribbon各个组件
在这里插入图片描述

最终各个组件关系图如下:

Ribbon各个组件关系图
在这里插入图片描述

下图是Debug时截取的RestTemplate实例变量图:

RestTemplate实例变量图
在这里插入图片描述

2、Ribbon 负载均衡调用流程

execute:74, RibbonLoadBalancerClient (org.springframework.cloud.netflix.ribbon)
intercept:55, LoadBalancerInterceptor (org.springframework.cloud.client.loadbalancer)
execute:88, InterceptingClientHttpRequest$InterceptingRequestExecution (org.springframework.http.client)
executeInternal:72, InterceptingClientHttpRequest (org.springframework.http.client)
executeInternal:48, AbstractBufferingClientHttpRequest (org.springframework.http.client)
execute:53, AbstractClientHttpRequest (org.springframework.http.client)
doExecute:660, RestTemplate (org.springframework.web.client)
execute:621, RestTemplate (org.springframework.web.client)
getForObject:295, RestTemplate (org.springframework.web.client)
greeting:40, ServiceBController (com.yh.stu.service)
....

org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient#execute 方法

@Override
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
	// serviceId为注册到Eureka里的服务名称,比如app-a
	// 1、获取负载均衡器,ZoneAwareLoadBalancer
	ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
	// 2、负载均衡器从服务中选择一台服务实例
	Server server = getServer(loadBalancer);
	if (server == null) {
		throw new IllegalStateException("No instances available for " + serviceId);
	}
	// 3、将Server实例封装为 RibbonServer 实例
	RibbonServer ribbonServer 
		= new RibbonServer(serviceId, server, isSecure(server,
			serviceId), serverIntrospector(serviceId).getMetadata(server));
	// 4、执行请求
	return execute(serviceId, ribbonServer, request);
}

2.1、为每个服务创建一个ApplicationContext

2.1.1、注册BeanDefinition

在容器启动 invokeBeanFactoryPostProcessors 阶段,调用 后置处理器 ConfigurationClassPostProcessor
调用栈如下:

// 5、注册 o.s.c.netflix.ribbon.RibbonAutoConfiguration 的BD
registerBeanDefinitions:52, RibbonClientConfigurationRegistrar (o.s.c.netflix.ribbon)
// 4、遍历[2]导入的BD注册器
loadBeanDefinitionsFromRegistrars:360, ConfigurationClassBeanDefinitionReader (o.s.context.annotation)
loadBeanDefinitionsForConfigurationClass:144, ConfigurationClassBeanDefinitionReader (o.s.context.annotation)
// 3、`BD读取器`从所有的配置类中读出BD
loadBeanDefinitions:116, ConfigurationClassBeanDefinitionReader (o.s.context.annotation)
// 2、(1)创建配置类解析器;(2)解析出所有的配置类(包括ImportSelector导入的ImportBeanDefinitionRegistrar);
processConfigBeanDefinitions:320, ConfigurationClassPostProcessor (o.s.context.annotation)
postProcessBeanDefinitionRegistry:228, ConfigurationClassPostProcessor (o.s.context.annotation)
// 1、按顺序调用所有的 BeanDefinitionRegistryPostProcessor 
invokeBeanDefinitionRegistryPostProcessors:272, PostProcessorRegistrationDelegate (o.s.context.support)
invokeBeanFactoryPostProcessors:92, PostProcessorRegistrationDelegate (o.s.context.support)
invokeBeanFactoryPostProcessors:687, AbstractApplicationContext (o.s.context.support)
refresh:525, AbstractApplicationContext (o.s.context.support)
refresh:122, EmbeddedWebApplicationContext (o.s.boot.context.embedded)
refresh:693, SpringApplication (o.s.boot)
refreshContext:360, SpringApplication (o.s.boot)
run:303, SpringApplication (o.s.boot)
run:1118, SpringApplication (o.s.boot)
run:1107, SpringApplication (o.s.boot)
main:12, AppBMain (com.yh.stu.service)
(1)RibbonAutoConfiguration 从哪来 ❓//TODO

第5步的 RibbonAutoConfiguration 从哪里来?

2.1.2、SpringClientFactory 设置配置
public class RibbonAutoConfiguration {
	@Autowired(required = false)
	private List<RibbonClientSpecification> configurations = new ArrayList<>();
	@Bean
	public SpringClientFactory springClientFactory() {
		SpringClientFactory factory = new SpringClientFactory();
		factory.setConfigurations(this.configurations);
		return factory;
	}
}

configurations 绑定的值就是在 RibbonClientConfigurationRegistrar 中注册的BD的实例

configurations = {ArrayList@6523}  size = 2
 0 = {RibbonClientSpecification@6569}
  "RibbonClientSpecification{name='default.o.s.c.netflix.ribbon.RibbonAutoConfiguration', configuration=[]}"
 1 = {RibbonClientSpecification@6570} 
	 "RibbonClientSpecification{name='default.o.s.c.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration'
 	, configuration=[class o.s.c.netflix.ribbon.eureka.EurekaRibbonClientConfiguration]}"

RibbonLoadBalancerClient#execute

1、获取负载均衡器 getLoadBalancer

ribbonLoadBalancer:137, RibbonClientConfiguration (o.s.c.netflix.ribbon)
CGLIB$ribbonLoadBalancer$8:-1, RibbonClientConfiguration$$EnhancerBySpringCGLIB$$9d596483 
			(o.s.c.netflix.ribbon)
invoke:-1, RibbonClientConfiguration$$EnhancerBySpringCGLIB$$9d596483$$FastClassBySpringCGLIB$$34722688 
			(o.s.c.netflix.ribbon)
invokeSuper:228, MethodProxy (o.s.cglib.proxy)
intercept:358, ConfigurationClassEnhancer$BeanMethodInterceptor (o.s.context.annotation)
ribbonLoadBalancer:-1, RibbonClientConfiguration$$EnhancerBySpringCGLIB$$9d596483 (o.s.c.netflix.ribbon)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
instantiate:162, SimpleInstantiationStrategy (o.s.beans.factory.support)
instantiateUsingFactoryMethod:588, ConstructorResolver (o.s.beans.factory.support)
instantiateUsingFactoryMethod:1181, AbstractAutowireCapableBeanFactory (o.s.beans.factory.support)
createBeanInstance:1075, AbstractAutowireCapableBeanFactory (o.s.beans.factory.support)
doCreateBean:513, AbstractAutowireCapableBeanFactory (o.s.beans.factory.support)
createBean:483, AbstractAutowireCapableBeanFactory (o.s.beans.factory.support)
getObject:312, AbstractBeanFactory$1 (o.s.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (o.s.beans.factory.support)
doGetBean:308, AbstractBeanFactory (o.s.beans.factory.support)
getBean:202, AbstractBeanFactory (o.s.beans.factory.support)
resolveCandidate:208, DependencyDescriptor (o.s.beans.factory.config)
doResolveDependency:1138, DefaultListableBeanFactory (o.s.beans.factory.support)
resolveDependency:1066, DefaultListableBeanFactory (o.s.beans.factory.support)
resolveAutowiredArgument:835, ConstructorResolver (o.s.beans.factory.support)
createArgumentArray:741, ConstructorResolver (o.s.beans.factory.support)
instantiateUsingFactoryMethod:467, ConstructorResolver (o.s.beans.factory.support)
instantiateUsingFactoryMethod:1181, AbstractAutowireCapableBeanFactory (o.s.beans.factory.support)
createBeanInstance:1075, AbstractAutowireCapableBeanFactory (o.s.beans.factory.support)
doCreateBean:513, AbstractAutowireCapableBeanFactory (o.s.beans.factory.support)
createBean:483, AbstractAutowireCapableBeanFactory (o.s.beans.factory.support)
getObject:312, AbstractBeanFactory$1 (o.s.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (o.s.beans.factory.support)
doGetBean:308, AbstractBeanFactory (o.s.beans.factory.support)
getBean:197, AbstractBeanFactory (o.s.beans.factory.support)
preInstantiateSingletons:761, DefaultListableBeanFactory (o.s.beans.factory.support)
finishBeanFactoryInitialization:867, AbstractApplicationContext (o.s.context.support)
refresh:543, AbstractApplicationContext (o.s.context.support)
/* 6、创建AnnotationConfigApplicationContext实例并设置相应的属性
	SpringClientFactory 父类 NamedContextFactory 属性:
	{
		defaultConfigType:RibbonClientConfiguration.class
		,propertySourceName:ribbon
		,propertyName:ribbon.client.name
	}
	在NamedContextFactory 中创建 AnnotationConfigApplicationContext并进行初始化
*/
createContext:116, NamedContextFactory (o.s.c.context.named)
//5、从ConcurrentHashMap中找出服务对应的AnnotationConfigApplicationContext
//,并从中获取ILoadBalancer.class的实例
getContext:85, NamedContextFactory (o.s.c.context.named)
getContext:120, SpringClientFactory (o.s.c.netflix.ribbon)
getInstance:121, NamedContextFactory (o.s.c.context.named)
getInstance:110, SpringClientFactory (o.s.c.netflix.ribbon)
getLoadBalancer:59, SpringClientFactory (o.s.c.netflix.ribbon)
//4、调用 RibbonLoadBalancerClient 持有的SpringClientFactory实例的getLoadBalancer方法
//获取ILoadBalancer.class的实例
getLoadBalancer:141, RibbonLoadBalancerClient (o.s.c.netflix.ribbon)
//3、调用 LoadBalancerInterceptor 持有的 RibbonLoadBalancerClient 实例的getLoadBalancer方法
execute:72, RibbonLoadBalancerClient (o.s.c.netflix.ribbon)
intercept:55, LoadBalancerInterceptor (o.s.c.client.loadbalancer)
// 2、本实例持有 LoadBalancerInterceptor 的实例,调用其intercept方法
execute:88, InterceptingClientHttpRequest$InterceptingRequestExecution (o.s.http.client)
// 1、创建InterceptingRequestExecution实例,并执行请求
executeInternal:72, InterceptingClientHttpRequest (o.s.http.client)
executeInternal:48, AbstractBufferingClientHttpRequest (o.s.http.client)
execute:53, AbstractClientHttpRequest (o.s.http.client)
// 一、根据URI,创建 ClientHttpRequest实例 并执行execute
doExecute:660, RestTemplate (o.s.web.client)
execute:621, RestTemplate (o.s.web.client)
getForObject:295, RestTemplate (o.s.web.client)
greeting:40, ServiceBController (com.yh.stu.service)
ZoneAwareLoadBalancer
在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java硕哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值