Ribbon详解与实例

前言:  Ribbon是客户端 负载均衡的工具。

 

第一步:Ribbon 初步配置

     

     1.1  在pom.xml文件中添加如下依赖

 

   <!-- Ribbon相关 -->
   <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-eureka</artifactId>
   </dependency>
   <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-ribbon</artifactId>
   </dependency>
   <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-config</artifactId>
   </dependency>
  </dependencies>

   

 1.2 在application.yml文件中

 

 

eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/      ,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

 

 

1.3  在RestTemplate配置类中添加@LoadBalanced

 

 

@Configuration
public class ConfigBean {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return  new RestTemplate();
    }

   /* @Bean
    public IRule myRule(){
        return new RandomRule();
    }*/
}

1.4  主启动类上面添加注解@EnableEurekaClient注解

 

 

@SpringBootApplication
@EnableEurekaClient
public class ConsumerDeptApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerDeptApplication.class,args);
    }
}

 

1.5 在服务消费方的controller方法中,修改url为要调用微服务的名称

 

private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT";

@RequestMapping(value = "/consumer/discovery")
public Object discovery(){

    return restTemplate.getForObject(rest_url+ "/dept/discovery",Object.class);
}

 

 

总结:上面的步骤 是Ribbon和Eureka的整合,Consumer可以直接调用微服务名称而不用再关心地址和端口号

 

第二部分:负载均衡

 

        一个服务提供方部署成集群模式,意思就是同一个微服务部署在多个服务器上面,服务消费者(客户端)通过Ribbo完成负载均衡并访问要访问的微服务
   

        Ribbon在工作时分成两步
            第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server.
            第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。
            其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。

 


    

 

 第三部分:自定义负载均衡算法

 

          

3.1         IRule组件:根据特定算法,从注册中心服务列表中选择一个要访问的服务,默认有七种算法,默认轮询算法。

我现在想用随机算法,在配置类中添加下面代码

@Bean
public IRule myRule(){
    return new RandomRule();
}

 

3.2   自定义负载均衡算法,不用出厂自带的

 

3.2.1  在主启动类添加@RibbonClient注解,这个注解作用,在启动微服务的时候去加载我们自定义的Ribbon配置类,从而使我们自己定义的算法生效  

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "MICROSERVICECLOUD-DEPT",configuration = MySelfRule.class)
public class ConsumerDeptApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerDeptApplication.class,args);
    }
}

3.2.2      自定义ribbon配置类(如下所示),不能放在@ComponentScan所扫描的当前包及子包下面,否则我们自定义的这个配置类就会被所有的ribbon客户端所共享,也就达不到特殊化定制化的目的了

 

@Configuration
public class MySelfRule {

    @Bean
    public IRule mySelRule(){

        return new RandomRule_ZY();
    }
}

//我自定义的算法
public class RandomRule_ZY extends AbstractLoadBalancerRule
{

   // total = 0 // 当total==5以后,我们指针才能往下走,
   // index = 0 // 当前对外提供服务的服务器地址,
   // total需要重新置为零,但是已经达到过一个5次,我们的index = 1
   // 分析:我们5次,但是微服务只有8001 8002 8003 三台,OK?
   // 
   
   
   private int total = 0;           // 总共被调用的次数,目前要求每台被调用5次
   private int currentIndex = 0;  // 当前提供服务的机器号

   public Server choose(ILoadBalancer lb, Object key)
   {
      if (lb == null) {
         return null;
      }
      Server server = null;

      while (server == null) {
         if (Thread.interrupted()) {
            return null;
         }
         List<Server> upList = lb.getReachableServers();
         List<Server> allList = lb.getAllServers();

         int serverCount = allList.size();
         if (serverCount == 0) {
            /*
             * No servers. End regardless of pass, because subsequent passes only get more
             * restrictive.
             */
            return null;
         }

//       int index = rand.nextInt(serverCount);// java.util.Random().nextInt(3);
//       server = upList.get(index);

         
//       private int total = 0;           // 总共被调用的次数,目前要求每台被调用5次
//       private int currentIndex = 0;  // 当前提供服务的机器号
            if(total < 5)
            {
               server = upList.get(currentIndex);
               total++;
            }else {
               total = 0;
               currentIndex++;
               if(currentIndex >= upList.size())
               {
                 currentIndex = 0;
               }
            }

         if (server == null) {
            /*
             * The only time this should happen is if the server list were somehow trimmed.
             * This is a transient condition. Retry after yielding.
             */
            Thread.yield();
            continue;
         }

         if (server.isAlive()) {
            return (server);
         }

         // Shouldn't actually happen.. but must be transient or a bug.
         server = null;
         Thread.yield();
      }

      return server;

   }

   @Override
   public Server choose(Object key)
   {
      return choose(getLoadBalancer(), key);
   }

   @Override
   public void initWithNiwsConfig(IClientConfig clientConfig)
   {
      // TODO Auto-generated method stub

   }
}

 


版权声明:本文为weixin_44582492原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。