【Java】Ribbon - 初始化

简单示例

Ribbon的使用在Eureka - 简单示例已经提过了一下,我们可以把provider复制一份出来,修改端口并注册到注册中心,如下图所示(代码跟之前的雷同,就不贴了):
【Java】Ribbon - 初始化
核心调用代码:

ResponseEntity<String> forEntity = restTemplate.getForEntity("http://eureka-provider/getInfo?name=" + name, String.class);

@Bean

@LoadBalanced

public RestTemplate restTemplate() {

return new RestTemplate();

}

在url里并没有写ip和端口,而是应用名称。访问Consumer的地址,可以看到轮询的访问两个Provider。

源码分析

@RibbonClients

还是从spring.factories说起,在Eureka Client和Ribbon的spring.factories有以下内容:

// Ribbon

org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration

// Eureka Client

org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration

这两个类都有@RibbonClients注解,里面import了RibbonClientConfigurationRegistrar类。

@Configuration(proxyBeanMethods = false)

@Retention(RetentionPolicy.RUNTIME)

@Target({ ElementType.TYPE })

@Documented

@Import(RibbonClientConfigurationRegistrar.class)

public @interface RibbonClients {

RibbonClient[] value() default {};

Class<?>[] defaultConfiguration() default {};

}

RibbonClientConfigurationRegistrar实现了ImportBeanDefinitionRegistrar接口,这个接口是用来动态的创建bean,registerBeanDefinitions方法里,会处理使用@RibbonClients@RibbonClient注解的类,并调用下面的registerClientConfiguration方法。由于上面两个类使用了@RibbonClients注解,所以会创建两个RibbonClientSpecification类型的bean,名字分别为default.org.springframework.cloud.netflix.ribbon.RibbonAutoConfigurationdefault.org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration

// 其他代码略

private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name,

Object configuration) {

BeanDefinitionBuilder builder = BeanDefinitionBuilder

.genericBeanDefinition(RibbonClientSpecification.class);

builder.addConstructorArgValue(name);

builder.addConstructorArgValue(configuration);

registry.registerBeanDefinition(name + ".RibbonClientSpecification",

builder.getBeanDefinition());

}

SpringClientFactory

SpringClientFactory是创建RibbonClient负载均衡的工厂类,他会创建一个独立的ApplicationContext以及RibbonClient相关的bean,这个后面会继续讲解这个内容。在SpringClientFactory实例化的时候,会赋值configurations,这个configurations就是上面的RibbonClientSpecification。SpringClientFactory实例化的适合,在构造函数会传RibbonClientConfiguration.class,这个后面讲解作用。

@Bean

@ConditionalOnMissingBean

public SpringClientFactory springClientFactory() {

SpringClientFactory factory = new SpringClientFactory();

factory.setConfigurations(this.configurations);

return factory;

}

LoadBalancerClient

客户端负载均衡器,这里注入的上面的SpringClientFactory。

@Bean

@ConditionalOnMissingBean(LoadBalancerClient.class)

public LoadBalancerClient loadBalancerClient() {

return new RibbonLoadBalancerClient(springClientFactory());

}

LoadBalancerRequestFactory

这里注入的上面的LoadBalancerClient。

@Bean

@ConditionalOnMissingBean

public LoadBalancerRequestFactory loadBalancerRequestFactory(

LoadBalancerClient loadBalancerClient) {

return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers);

}

LoadBalancerInterceptor

主要是用于客户端请求的拦截,通过拦截实现负载均衡。这里注入的是LoadBalancerClient和LoadBalancerRequestFactory。

@Bean

public LoadBalancerInterceptor loadBalancerInterceptor(

LoadBalancerClient loadBalancerClient,

LoadBalancerRequestFactory requestFactory) {

return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);

}

RestTemplateCustomizer

restTemplate.setInterceptors(list),是给restTemplate增加LoadBalancerInterceptor,这个LoadBalancerInterceptor是上面注入的。

@Bean

@ConditionalOnMissingBean

public RestTemplateCustomizer restTemplateCustomizer(

final LoadBalancerInterceptor loadBalancerInterceptor) {

return restTemplate -> {

List<ClientHttpRequestInterceptor> list = new ArrayList<>(

restTemplate.getInterceptors());

list.add(loadBalancerInterceptor);

restTemplate.setInterceptors(list);

};

}

loadBalancedRestTemplateInitializerDeprecated

先看看LoadBalanced注解,这里引入的是@Qualifier

@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@Qualifier

public @interface LoadBalanced {

}

LoadBalancerAutoConfiguration类中,有这一行代码,他也引入了@LoadBalanced,我们之前Eureka - 简单示例,RestTemplate实例化的时候也是加@LoadBalanced注解的。他这个意思是只要加了@LoadBalanced注解的,都注入到restTemplates,所以我们如果没有在RestTemplate,就没办法注入到这里,也就没办法后续的拦截器注入。

@LoadBalanced

@Autowired(required = false)

private List<RestTemplate> restTemplates = Collections.emptyList();

在loadBalancedRestTemplateInitializerDeprecated中,由于是SmartInitializingSingleton类型的,所以会调用afterSingletonsInstantiated方法,return的部分就是这个方法。在这个方法中,会遍历上面@LoadBalanced的restTemplate,然后再一个个调用RestTemplateCustomizer的方法,实现拦截器注入。

@Bean

public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(

final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {

return () -> restTemplateCustomizers.ifAvailable(customizers -> {

for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {

for (RestTemplateCustomizer customizer : customizers) {

customizer.customize(restTemplate);

}

}

});

}

总结

【Java】Ribbon - 初始化

以上是 【Java】Ribbon - 初始化 的全部内容, 来源链接: utcz.com/a/91888.html

回到顶部