`

SpringCloud @LoadBalanced注解学习

 
阅读更多
当时我们说开启负载均衡很简单,只需要在RestTemplate的bean上再添加一个@LoadBalanced注解即可,所以本文我们就从这个注解开始我们的分析吧。
/**
     * 使用RestTemplate实现负载均衡
     * @return
     */
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }


首先我们来看看@LoadBalanced注解的源码:

/**
 * Annotation to mark a RestTemplate bean to be configured to use a LoadBalancerClient
 * @author Spencer Gibb
 */
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {
}


具体的配置是在哪里执行的呢?我们在LoadBalancerClient的包下面发现了一个类叫做LoadBalancerAutoConfiguration,看名字有点像是客户端负载均衡服务器的自动化配置类,我们来看看这个类的源码:

@Configuration
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
public class LoadBalancerAutoConfiguration {

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

    @Bean
    public SmartInitializingSingleton loadBalancedRestTemplateInitializer(
            final List<RestTemplateCustomizer> customizers) {
        return new SmartInitializingSingleton() {
            @Override
            public void afterSingletonsInstantiated() {
                for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
                    for (RestTemplateCustomizer customizer : customizers) {
                        customizer.customize(restTemplate);
                    }
                }
            }
        };
    }

    @Autowired(required = false)
    private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();

    @Bean
    @ConditionalOnMissingBean
    public LoadBalancerRequestFactory loadBalancerRequestFactory(
            LoadBalancerClient loadBalancerClient) {
        return new LoadBalancerRequestFactory(loadBalancerClient, transformers);
    }

    @Configuration
    @ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
    static class LoadBalancerInterceptorConfig {
        @Bean
        public LoadBalancerInterceptor ribbonInterceptor(
                LoadBalancerClient loadBalancerClient,
                LoadBalancerRequestFactory requestFactory) {
            return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
        }

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

    @Configuration
    @ConditionalOnClass(RetryTemplate.class)
    public static class RetryAutoConfiguration {
        @Bean
        public RetryTemplate retryTemplate() {
            RetryTemplate template =  new RetryTemplate();
            template.setThrowLastExceptionOnExhausted(true);
            return template;
        }

        @Bean
        @ConditionalOnMissingBean
        public LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory() {
            return new LoadBalancedRetryPolicyFactory.NeverRetryFactory();
        }
    }

    @Configuration
    @ConditionalOnClass(RetryTemplate.class)
    public static class RetryInterceptorAutoConfiguration {
        @Bean
        @ConditionalOnMissingBean
        public RetryLoadBalancerInterceptor ribbonInterceptor(
                LoadBalancerClient loadBalancerClient, LoadBalancerRetryProperties properties,
                LoadBalancedRetryPolicyFactory lbRetryPolicyFactory,
                LoadBalancerRequestFactory requestFactory) {
            return new RetryLoadBalancerInterceptor(loadBalancerClient, properties,
                    lbRetryPolicyFactory, requestFactory);
        }

        @Bean
        @ConditionalOnMissingBean
        public RestTemplateCustomizer restTemplateCustomizer(
                final RetryLoadBalancerInterceptor loadBalancerInterceptor) {
            return new RestTemplateCustomizer() {
                @Override
                public void customize(RestTemplate restTemplate) {
                    List<ClientHttpRequestInterceptor> list = new ArrayList<>(
                            restTemplate.getInterceptors());
                    list.add(loadBalancerInterceptor);
                    restTemplate.setInterceptors(list);
                }
            };
        }
    }
}


这个类的源码比较长,我们就来说一下这里的核心功能:

1.LoadBalancerAutoConfiguration类上有两个关键注解,分别是@ConditionalOnClass(RestTemplate.class)和@ConditionalOnBean(LoadBalancerClient.class),说明Ribbon如果想要实现负载均衡的自动化配置需要满足两个条件:第一个,RestTemplate类必须存在于当前工程的环境中;第二个,在Spring容器中必须有LoadBalancerClient的实现Bean。

2.ribbonInterceptor方法返回了一个拦截器叫做LoadBalancerInterceptor,这个拦截器的作用主要是在客户端发起请求时进行拦截,进而实现客户端负载均衡功能。

3.restTemplateCustomizer方法返回了一个RestTemplateCustomizer,这个方法主要用来给RestTemplate添加LoadBalancerInterceptor拦截器。

4.restTemplates是一个被@LoadBalanced注解修饰的RestTemplate对象列表,在loadBalancedRestTemplateInitializer方法中通过调用RestTemplateCustomizer中的customizef方法来给RestTemplate添加上LoadBalancerInterceptor拦截器。

从而实现了从http://服务名/hellohttp://域名/hello的转换。

RestTemplate从一个简单的服务请求控件变成了具有客户端负载均衡功能的请求控件。简而言之,就是RestTemplate发起一个请求,这个请求被LoadBalancerInterceptor给拦截了,拦截后将请求的地址中的服务逻辑名转为具体的服务地址,然后继续执行请求,就是这么一个过程。

转自:http://blog.csdn.net/u012702547/article/details/77940838









分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    SpringCloud-Project:SpringCloud的注册中心和服务以及消费

    Spring Cloud项目执行顺序 1 eureka-server-demo是注册中心(首先启动) 2 service-zuul-demo是网关,专门负责路由转发和过滤器(可以用与登录等等的校验) 3 service-member是服务提供者,启动会向配置文件中的注册...

    SpringCloud-2.0-order-Feign-8005.zip

    SpringCloud-2.0-order-Feign-8005.zip 使用feign技术,实现RestTemplate的@LoadBalanced类似的负载均衡操作

    02_SpringCloud客户端负载均衡Ribbon.md

    SpringCloud的复杂均衡 属于客户端;nginx辅助均衡属于服务器端 ,restTemplate 进行RPC调用.对外使用 rest http方式。DiscoveryClient 可以自己实现一个负载均衡的算法(使用请求总数 % 服务列表个数).算法文件跟新...

    73-Spring Cloud客户端负载均衡Ribbon笔记1

    Ribbon负载均衡机制Ribbon实现了客户端的负载均衡,调用服务使用的是用@LoadBalanced的RestTemplate:通过对其跟踪,定位到Load

    eureka 客户端-服务提供者

    本系列介绍的配置均基于 Spring Boot 2.1.1.RELEASE 版本和 Spring Cloud Greenwich.RC1 版本.Eureka客户端-生产者

    xd-springcloud

    springcloud 系列组件 Eureka 集群 Eureka-Server1 Eureka-Server2 Eureka-Server3 启动后显示如下: 服务提供方 xd-springcloud-provider 服务消费方 xd-springcloud-consumer 采用Ribbon的均衡负载 ...

    seata-business2.rar

    @LoadBalanced和RestTemplate负载均衡

    springboot启动类

    import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication ...

    SpringCloudAlibaba Nacos Client演示服务调用

    1,SpringCloudAlibaba Nacos Client演示服务调用 2,该演示只是演示调用,调用类使用RestTemplate 3,主要是使用名称,加上客户端负载均衡实现LoadBalanced

    高可靠性的Apache负载均衡服务器组的搭建 Apache集群

    How To Set Up A Loadbalanced High-Availability Apache Cluster 详细介绍了如何搭建一套基于Apache的服务器集群组 实现服务器负载均衡

    Documentation:服务器配置脚本

    服务器脚本AWS Cloudformation 模板: AutoScaling-MultipleZones-LoadBalanced.template AutoScaling-MultipleZones-LoadBalanced-Notifications.template 灯组灯堆栈MultiZone.template 灯堆单实例模板灯堆栈单...

Global site tag (gtag.js) - Google Analytics