zoukankan      html  css  js  c++  java
  • Spring Cloud (四):客户端实现负载均衡

    Robbin 是 Netflix 开发的实现客户端负载均衡的组件,通常和 Eureka 一起使用,前面的例子中 Eureka Consumer 已经使用了负载均衡

    在前面的 Eureka 服务发现的基础上做一些修改

    因为 Eureka 依赖已经包含了 Robbin,所以无需导入 Robbin

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
    

    启动两个 Producer,只是 port 以及返回的内容不同

    server.port=8762
    
        @RequestMapping("/api")
        public String index() {
            return "Greetings from Eureka Producer 1!";
        }
    
    server.port=8763
    
        @RequestMapping("/api")
        public String index() {
            return "Greetings from Eureka Producer 2!";
        }
    

    在 Consumer 加入 RestTemplate 的配置

    @Configuration
    public class RestTemplateConfig {
    
        @Bean
        @LoadBalanced  // 实现 Ribbon 负载均衡的 RestTemplate
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
        
        @Bean
        public IRule loadbalanceRule(){
            return new RandomRule();   // 随机策略
        }
    }
    

    添加使用这个 RestTemplate 的接口

    @RestController
    public class Controller {
        @Autowired
        private LoadBalancerClient loadBalancer;
        
        @Autowired
        private DiscoveryClient discoveryClient;
     
        @Autowired
        private RestTemplate restTemplate;  // 具有负载均衡的 restTemplate
        
        @RequestMapping("/queryService")
        public String query() {
            List<ServiceInstance> instances = discoveryClient.getInstances("service-provider-1");
            StringBuilder urls= new StringBuilder();
            for(ServiceInstance instance : instances){
                urls.append(instance.getHost()+":"+instance.getPort()).append(",");
            }
            return "service name : service-provider-1<br>" + "host : " + urls.toString();
        }
        
        @RequestMapping("/discover")
        public Object discover() {
            // 通过 LoadBalancerClient 获取 service-provider-1 服务的其中一个 host
            // 可以看到有时返回 8762 端口,有时返回 8763 端口,这样就实现了负载均衡
            return loadBalancer.choose("service-provider-1").getUri().toString();
        }
        
        @RequestMapping("/rest")
        public String rest() {
            // 这里直接使用注册在 Eureka 的 service id 也就是 service-provider-1
            // 这样 RestTemplate 会自动实现负载均衡
            String forObject = restTemplate.getForObject("http://service-provider-1/api", String.class);
            return forObject;
        }
    }
    

    Ribbon 的负载均衡策略可以用代码配置,也可以通过配置文件配置

        @Bean
        public IRule loadbalanceRule(){
            return new RandomRule();   // 随机策略
        }
    
    @Configuration
    @RibbonClient(name="service-provider-1",configuration=RestTemplateConfig.class)
    public class NewRobbinConfig {
    
    }
    
    service-provider-1.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
    


    Robbin 也可以和 Consul 集成,实际上前面的例子中 Consul Consumer 同样已经使用了负载均衡

    在前面的 Consul 服务发现的基础上做一些修改

    因为 Consul 依赖已经包含了 Ribbon,所以无需导入 Ribbon

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    

    启动两个 Producer,只是 port 以及返回的内容不同

    # application.yml
    server:
      port: 8501
    
    // Controller.java
        @RequestMapping("/hello")
        public String hello() {
            return "consul-service-1 instance-1";
        }
    
    # application.yml
    server:
      port: 8502
    
        @RequestMapping("/hello")
        public String hello() {
            return "consul-service-1 instance-2";
        }
    

    在 Consumer 端加入 RestTemplate 的配置

    @Configuration
    public class RestTemplateConfig {
    
        @Bean
        @LoadBalanced  // 实现 Ribbon 负载均衡的 RestTemplate
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
        
        @Bean
        public IRule loadbalanceRule(){
            return new RandomRule();   // 随机策略
        }
    }
    

    添加使用这个 RestTemplate 的接口

    public class Controller {
        @Autowired
        private LoadBalancerClient loadBalancer;
        
        @Autowired
        private DiscoveryClient discoveryClient;
     
        @Autowired
        private RestTemplate restTemplate;  // 具有负载均衡的restTemplate
        
        @RequestMapping("/services")
        public Object services() {
            // 获取 consul-service-1 服务的信息
            // 这里会返回两个,因为有两个服务注册了这个名字
            return discoveryClient.getInstances("consul-service-1");
        }
     
        @RequestMapping("/discover")
        public Object discover() {
            // 通过 LoadBalancerClient 获取 consul-service-1 服务的其中一个 host
            // 可以看到有时返回 8501 端口,有时返回 8502 端口,这样就实现了负载均衡
            return loadBalancer.choose("consul-service-1").getUri().toString();
        }
        
        @RequestMapping("/rest")
        public String rest(){
            // 这里直接使用注册在 Consul 的 service id 也就是 consul-service-1
            // 这样 RestTemplate 会自动实现负载均衡
            String forObject = restTemplate.getForObject("http://consul-service-1/hello", String.class);
            return forObject;
        }
    }
    

    Ribbon 的负载均衡策略可以用代码配置,也可以通过配置文件配置

        @Bean
        public IRule loadbalanceRule(){
            return new RandomRule();   // 随机策略
        }
    
    @Configuration
    @RibbonClient(name="consul-service-1",configuration=RestTemplateConfig.class)
    public class NewRobbinConfig {
    
    }
    
    consul-service-1:
      ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
    


  • 相关阅读:
    go语言中文网
    理解Golang包导入
    如何保证对象的唯一性
    模拟java.util.Collection一些简单的用法
    静态代码块,构造代码块,局部代码块演示
    java中paint方法和paintComponent方法的不同
    java中异常注意问题(发生在多态是的异常问题)
    java中异常注意的细节2
    java中异常注意的细节1
    java中匿名类的注意细节
  • 原文地址:https://www.cnblogs.com/moonlight-lin/p/14197411.html
Copyright © 2011-2022 走看看