美文网首页spring-cloud
SpringCloud组件之Ribbon深入

SpringCloud组件之Ribbon深入

作者: 高默思 | 来源:发表于2019-03-23 14:54 被阅读0次

    本篇文章主要介绍Ribbon的集中负载均衡策略,以及Ribbon的各种常用配置

    在上一节SpringCloud组件之Ribbon中,实现了一个Ribbon的Helloword,使用的是Spring Eureka 和Spring Ribbon结合使用,并且使用Ribbon的默认轮询注册清单的负载均衡策略。

    Ribbon配置

    Ribbon参数配置通常有两种方式:全局配置和知道客户端配置

    全局配置

    通用格式:ribbon.<key>=<value>
    key:表示参数名称
    value:表示参数值
    例如:全局配置Ribbon创建连接的超时时间
    \color{green}{ribbon.ConnectTimeout=250}

    客户端配置

    针对指定的服务进行配置 通用格式 <client>.ribbon.<key>=<value>
    key:表示参数名称
    value:表示参数值
    client:表示客户端服务的名称
    例如:我们调用的Rest请求时是 http://hello-service/hello/hello,现在我们来为服务hello-service服务指定他的实例清单(和注册中心中的服务清单一样)
    \color{green}{hello-service.ribbon.listOfServers=localhost:8011,localhost:8012}

    可以查看com.netflix.client.config.CommonClientConfigKey类,获取详细配置内容

    Ribbon负载均衡策略

    下面将单独使用Spring Ribbon组件来介绍几种Ribbon负载均衡策略,单独使用Ribbon组件,不结合Eureka组件的不同之处在于,不能根据服务名称自动从Eureka的注册中心获取一个服务的实例清单,必须手动在配置文件中添加服务实例清单。

    Ribbon的各种负载均衡策略的顶层IRule接口 IRule继承结构图

    RandomRule策略(com.netflix.loadbalancer.RandomRule)

    RandomRule策略:该策略实现了从服务实例清单中随机选择一个服务实例,作为请求服务对象。

    首先创建一个SpringBoot的服务。
    pom.xml

    <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.3.RELEASE</version>
            <relativePath/>
    </parent>
    <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <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-commons</artifactId>
            </dependency>
        </dependencies>
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Dalston.SR3</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    

    application.yaml

    server:
      port: 8015 #端口号
    spring:
      application:
        name: loadbalance-service # 服务名称
    
    #取消Ribbon使用Eureka
    ribbon:
      eureka:
        enabled: false;
    
    #设置一个服务客户端的Ribbon配置
    helloword-service:
      ribbon:
        #配置Ribbon能访问 的微服务节点,多个节点用逗号隔开
        listOfServers: localhost:8001,localhost:8002,localhost:8003,localhost:8004,localhost:8005
        #配置Ribbon负载均衡策略
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule;
    

    由于不需要Eureka组件,所以需要取消Ribbon使用Eureka,由于没有注册中心,需要手动添加一个服务客户端的所有实例,最后设置负载均衡策略

    LoadBalanceController类

    @RestController
    @RequestMapping("loadbalance")
    public class LoadBalanceController {
        @Autowired
        RestTemplate restTemplate;
        @Autowired
        private LoadBalancerClient loadBalancer;
    
        @RequestMapping(value = "/hello",method = RequestMethod.GET)
        public String getRequest(){
            ServiceInstance instance = loadBalancer.choose("helloword-service");
            String host = instance.getHost();
            int port = instance.getPort();
            System.out.println("负载均衡请求:" + host + ":" +port);
            return "负载均衡请求:" + host + ":" +port;
        }
    }
    

    LoadBalanceMain类

    @SpringBootApplication
    public class LoadBalanceMain {
        @Bean
        @LoadBalanced
        RestTemplate getrestTemplate(){
            return new RestTemplate();
        }
        @Bean
        public IRule ribbonRule() {
            return new RandomRule();
        }
        public static void main(String[] args) {
            SpringApplication.run(LoadBalanceMain.class,args);
        }
    }
    
    

    ribbonRule()方法的返回值表示Ribbon选择的复杂你均衡策略,同时将该对象加载到 Spring容器中

    启动main,在浏览器中输入http://localhost:8015/loadbalance/hello,多次请求,可以看到页面呈现不同的请求路径。而且这些请求都是随机出现,查看后台打印

    后台打印

    RoundRobinRule策略(com.netflix.loadbalancer.RandomRule)

    RoundRobinRule:该策略实现了按照线性轮询的方式一次轮询服务清单上的每个服务实例。

    结合上面的例子,修改两个部分,一个是application.yaml中
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule

    一个是LoadBalanceMain 中 修改ribbonRule()的返回值

    @Bean
        public IRule ribbonRule() {
            return new RoundRobinRule();
        }
    
    启动main 查看页面展示和后台打印 后台打印

    RetryRule策略(com.netflix.loadbalancer.RetryRule)

    RetryRule:该策略具备重试机制的实例选择功能,在给定时间内能够得到选择到具体的服务实例就返回,当超过时间还有没选到就返回null,参数maxRetryMillis控制这个超时时间。

    WeightedResponseTimeRule策略(com.netflix.loadbalancer.WeightedResponseTimeRule)

    WeightedResponseTimeRule:该策略是对RoundRobinRule的扩展,增加了根据实例的响应时间来计算权重,并从权重中选择对应的实例。该策略实现主要有三个核心内容

    定时任务

    WeightedResponseTimeRule策略在初始化的时候会启动一个定时任务,默认每隔30秒计算一次每个服务实例的权重

    权重计算
    累计所有实例的响应时间,得到总的totalResponseTime,然后为实例清单中的每个实例逐个计算权重,计算公式为
    weightSoFar = weightSoFar + totalResponseTime - 该实例的平均响应时间
    weightSoFar 起始为零
    例子
    有A,B,C,D四个实例,他们的平均响应时间是10,40,80,100,
    计算总的响应时间10+40+80+100 =230
    计算各个实例的权重
    A: 230-10=220
    B:220+(230-40)=410
    C:410+(230-80)=560
    D:560+(230-100)=690;
    计算各个实例的权重区间
    A:[0,220]
    B:(220,410]
    C:(410,560]
    D:(560,690)

    实例选择
    WeightedResponseTimeRule策略会在[0,最大权重值)之间随机选取一个数,然后在看这个数落在哪个实例的权重区间内,接着WeightedResponseTimeRule就会去选择该实例。

    可以看出,响应时间越短,获取的权重区间就会越大,随机数落到的概率就会越大

    ClientConfigEnableRoundRobinRule策略(com.netflix.loadbalancer.ClientConfigEnableRoundRobinRule)

    ClientConfigEnableRoundRobinRule:该策略一般不直接使用,有些高级的策略会继承该类,完成一些高级的策略,ClientConfigEnableRoundRobinRule策略默认使用
    RoundRibinRule的线性轮询机制

    BestAvailableRule策略(com.netflix.loadbalancer.BestAvailableRule)

    BestAvailableRule策略继承ClientConfigEnableRoundRobinRule,通过遍历负载均衡中维护的所有服务实例,会过滤掉故障实例,并找出并发数请求数最小的实例,所以该策略的特性就是选出最空闲的实例

    PredicateBasedRule策略(com.netflix.loadbalancer.PredicateBasedRule)

    PredicateBasedRule策略继承ClientConfigEnableRoundRobinRule,该策略主要特性是“先过滤,在轮询”,也就是先过滤掉一些实例,得到过滤后的实例清单,然后轮询该实例清单,PredicateBasedRule中“过滤”功能没有实现,需要继承它的类完成,也就是说不同继承PredicateBasedRule的类有不同的“过滤特性”

    AvailabilityFilteringRule策略(com.netflix.loadbalancer.PredicateBasedRule)

    AvailabilityFilteringRule策略继承PredicateBasedRule策略的“先过滤,在轮询”特性,
    AvailabilityFilteringRule策略的过滤特性是
    1:是否故障,即断路器是否生效已断开
    2:实例的并发请求数大于阈值,默认2的32次方减一,该阈值可以通过
    <clientName>.<nameSpace>.ActiveConnectionsLimit来设置,只要满足其中一个那么就会过滤掉

    相关文章

      网友评论

        本文标题:SpringCloud组件之Ribbon深入

        本文链接:https://www.haomeiwen.com/subject/wmdsvqtx.html