博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

SpringCloud - 04负载均衡Ribbon

Posted on 2021-01-15 15:22  Kingdomer  阅读(135)  评论(0)    收藏  举报

SpringCloud - 04负载均衡Ribbon

(1)负载均衡简介

负载均衡LB(Load Balance): 将用户的请求平摊的分配到多个服务上,从而达到系统的HA。

常见负载均衡有软件Nginx、LVS, 硬件F5等。在中间件 Dubbo和SpringCloud均提供了负载均衡,SpringCloud可自定义负载均衡算法。

集中式LB: 在服务的消费方和提供方之间使用独立的LB设施,由该设施负责把访问请求通过某种策略转发至服务的提供方。

进程内LB: 将LB逻辑集成到消费方,消费方从服务注册中心获取有哪些地址可用,然后再从这些地址中选择出一个合适的服务器。

                                                                                      

 

Spring Cloud Ribbon 是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

Ribbon客户端组件提供一系列完善的配置项,如连接超时、重试等。

在配置文件中列出Load Balancer后面所有的机器,Ribbon自动基于某种规则(简单轮询、随机连接等)去连接这些机器。

Ribbon在工作时分为两步

第一步: 选择Eureka Server, 优先选择在同一个区域内负载较少的server。

第二步: 根据用户指定的策略,再从server取到的服务注册列表中选择一个地址。

 

(2)部署构建Consumer

(2.1)修改POM文件

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

(2.2)修改application.yml

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: microservice-dept-consumer
    prefer-ip-address: true

(2.3)添加注解@LoadBalanced

@Configuration
public class ConfigBean {

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

(2.4)修改主启动类

@SpringBootApplication
@EnableEurekaClient
public class DeptConsumerApplication {}

(2.5)修改客户端访问类Controller

@RestController
public class DeptConsumerController {

//    private final static String REST_DEPT_URL_PREFIX ="http://localhost:8001";
    private final static String REST_DEPT_URL_PREFIX ="http://MICROSERVICECLOUD-DEPT-PROVIDER";

}

(2.6)开启多个Provider

spring:
  application:
    name: microservicecloud-dept-provider  // 3个服务提供者一致

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
  instance:
    instance-id: microservice-dept-provider2
    prefer-ip-address: true

(2.7)测试: 先启动Eureka集群,然后启动 provider, 再启动 consumer

              

总结: Ribbon就是一个软负载均衡的客户端组件,可以和其他所需请求的客户端结合使用,不仅仅只是与Eureka结合。

 

(3)负载均衡算法

IRule: 根据特定算法,从服务列表中选取一个要访问的服务

  • RoundRobinRule: 轮询
  • RandomRule:     随机
  • AvailabilityFilteringRule: 会先过滤由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,
    • 然后对剩余的服务列表按照轮询策略进行
  • WeightedResponseTimeRule:  根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大,被选中可能越大。
    • 刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够会切换到WeightedResponseTimeRule。
  • RetryRule:         先按照RoundRobinRule的策略获取服务,获取服务失败则在指定时间内进行重试,获取可用服务。
  • BestAvailableRule: 先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的
  • ZoneAvoidanceRule: 默认规则,复合判断server所在区域的性能和server的可用性选择服务器

(3.1)配置负载均衡算法

@Configuration
public class ConfigBean {
    // 省略其他代码
    @Bean
    public IRule myRule(){
        return new RandomRule();  // return new RoundRobinRule();
    }
}

 

(3.2)自定义负载均衡算法

(3.2.1)负载均衡算法: 轮询策略,每个服务器要求被调用5次。

public class RandomRule_ZY extends AbstractLoadBalancerRule {

    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    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){
                return null;
            }

            if (total < 5){
                server = upList.get(currentIndex);  
                total++;
            }else {
                total = 0;
                currentIndex++;
                if (currentIndex >= upList.size()){
                    currentIndex = 0;
                }
            }
        }

        return server;
    }

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

 

(3.2.2)配置类 

@Configuration
public class MySelfRule {
    @Bean
    public IRule myRule(){
        return new RandomRule_ZY();
    }
}

 

注意: 这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则配置类会被所有Ribbon客户端共享,起不到特殊定制目的。

(3.2.3)主启动类: 在启动该微服务时加载自定义Ribbon配置类,使配置生效。

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