Spring Clould 负载均衡学习笔记

RestTemplate负载均衡

调用代码

@RestController
public class UserController {

    @Autowired
    RestTemplate restTemplate;


    @Autowired
    LoadBalancerClient loadBalancerClient;

    //方式一
    //    @Bean
    //    //@LoadBalanced  开启客户端负载均衡,即restTemplate.getForObject 必须通过服务名称访问
    //    public RestTemplate restTemplate(){
    //        return  new RestTemplate();
    //    }
    //方式二
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){
        return  restTemplateBuilder.build();
    }


    @GetMapping("/user/orders")
    public String getUserOrders(){
        String returnStr="";
        ServiceInstance serviceInstance=loadBalancerClient.choose("xue-service-order");
        String requestUrl=String.format("http://%s:%s",serviceInstance.getHost(),serviceInstance.getPort()+"/orders");
        System.out.println(requestUrl);
        returnStr+=restTemplate.getForObject(requestUrl,String.class);
        return returnStr;
   }

}

调用方配置

server.port=8088
spring.application.name=xue-service-user
xue-service-order.ribbon.listOfServers=127.0.0.1:8086,127.0.0.1:8087

@LoadBalanced 负载均衡

调用代码

@RestController
public class UserController2 {

   @Autowired
   RestTemplate restTemplate;

   //方式一
   //开启客户端负载均衡,即restTemplate.getForObject 必须通过服务名称访问
   //    @Bean
   //    @LoadBalanced
   //    public RestTemplate restTemplate(){
   //        return  new RestTemplate();
   //    }
   //方式二
   @Bean
   @LoadBalanced
   public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){
       return  restTemplateBuilder.build();
   }


   @GetMapping("/user/orders2")
   public String getUserOrders(){
       String returnStr="";
       String requestUrl="http://xue-service-order/orders";
       System.out.println(requestUrl);
       returnStr+=restTemplate.getForObject(requestUrl,String.class);
       return returnStr;
  }

}

@LoadBalanced原理

注解内容分析,

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {
}

@Qualifier 注解起到的作用

public class TestClass {
   private String name;

   public TestClass(String name) {
       this.name = name;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }
} 
@Configuration
public class TestConfiguration {

   @Bean("testClass1")
   TestClass testClass(){
       return new TestClass("testClass1");
   }
   @Qualifier
   @Bean("testClass2")
   TestClass testClass2(){
       return  new TestClass("testClass2");
   }

}
@RestController
public class TestController {

   @Autowired
   @Qualifier
   List<TestClass> testClassList= Collections.emptyList();


   @GetMapping("/test")
   public Object getTest() {
       return testClassList;
   }
}

接口返回结果, [{“name”:“testClass2”}],说明@Qualifier 注解标记的bean 会被自动扫描到,并装配到@Qualifier 标记的 List testClassList 中,
所以 @LoadBalanced也有同样的作用

@LoadBalanced如何进行负载均衡的

入口 LoadBalancerAutoConfiguration 自动装配类

主要将拦截器加入到restTemplates

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({RestTemplate.class})
@ConditionalOnBean({LoadBalancerClient.class})
@EnableConfigurationProperties({LoadBalancerRetryProperties.class})
public class LoadBalancerAutoConfiguration {
    //和我们案例中的下段代码作用一致,获得所有标记了,@LoadBalanced的RestTemplate的bean
    //@Autowired
    //@Qualifier
    //List testClassList= Collections.emptyList();
    @LoadBalanced
    @Autowired(
        required = false
    )
    private List<RestTemplate> restTemplates = Collections.emptyList();
    @Autowired(
        required = false
    )
    private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();

    public LoadBalancerAutoConfiguration() {
    }
    //下面都是利用@Bean  去装配,最终将拦截器装配到restTemplates  中(restTemplate.setInterceptors(list);)
    @Bean
    public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
        return () -> {
            restTemplateCustomizers.ifAvailable((customizers) -> {
                Iterator var2 = this.restTemplates.iterator();

                while(var2.hasNext()) {
                    RestTemplate restTemplate = (RestTemplate)var2.next();
                    Iterator var4 = customizers.iterator();

                    while(var4.hasNext()) {
                        RestTemplateCustomizer customizer = (RestTemplateCustomizer)var4.next();
                        customizer.customize(restTemplate);
                    }
                }

            });
        };
    }

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

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({RetryTemplate.class})
    public static class RetryInterceptorAutoConfiguration {
        public RetryInterceptorAutoConfiguration() {
        }

        @Bean
        @ConditionalOnMissingBean
        public RetryLoadBalancerInterceptor ribbonInterceptor(LoadBalancerClient loadBalancerClient, LoadBalancerRetryProperties properties, LoadBalancerRequestFactory requestFactory, LoadBalancedRetryFactory loadBalancedRetryFactory) {
            return new RetryLoadBalancerInterceptor(loadBalancerClient, properties, requestFactory, loadBalancedRetryFactory);
        }

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

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({RetryTemplate.class})
    public static class RetryAutoConfiguration {
        public RetryAutoConfiguration() {
        }

        @Bean
        @ConditionalOnMissingBean
        public LoadBalancedRetryFactory loadBalancedRetryFactory() {
            return new LoadBalancedRetryFactory() {
            };
        }
    }

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnMissingClass({"org.springframework.retry.support.RetryTemplate"})
    static class LoadBalancerInterceptorConfig {
        LoadBalancerInterceptorConfig() {
        }

        @Bean
        public LoadBalancerInterceptor ribbonInterceptor(LoadBalancerClient loadBalancerClient, LoadBalancerRequestFactory requestFactory) {
            return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
        }

        @Bean
        @ConditionalOnMissingBean
        public RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {
            return (restTemplate) -> {
                List<ClientHttpRequestInterceptor> list = new ArrayList(restTemplate.getInterceptors());
                list.add(loadBalancerInterceptor);
                restTemplate.setInterceptors(list);
            };
        }
    }
}

如何负载均衡

restTemplate.getForObject(requestUrl,String.class);
在调用的时候,会触发拦截器LoadBalancerInterceptor.intercept(),this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution)); LoadBalancerClient的实现类RibbonLoadBalancerClient,执行execute(String serviceId, LoadBalancerRequest request, Object hint),拦截器会获取目标的地址列表ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId)利用工厂模式,由serviceId获取ILoadBalancer 实例;,并通过负载规则Rule(默认轮训,即记录调用次数)实现目标服务的负载均衡的调取

你可能感兴趣的:(spring,clould实战,spring)