关于java:Ribbon-初始化

31次阅读

共计 4583 个字符,预计需要花费 12 分钟才能阅读完成。

简略示例

Ribbon 的应用在 Eureka – 简略示例曾经提过了一下,咱们能够把 provider 复制一份进去,批改端口并注册到注册核心,如下图所示(代码跟之前的雷同,就不贴了):

外围调用代码:

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);
            }
        }
    });
}

总结

正文完
 0