• Ribbon的基础知识


    概述

    Ribbon实现客户端的负载均衡,Feign内部是默认集成Ribbon的。本文会讲解Ribbon的常用的配置方式以及负载规则。

    配置方式

    配置Ribbon有两种方式,第一种是在@FeignClient中的configuration设置自定义的类

    @FeignClient(value = "user", configuration = RibbonConfig.class)

    Ribbon配置类RibbonConfig设置规则

    @Configuration
    public class RibbonConfig {
        @Bean
        public IRule ribbonRule() {
            return new RandomRule(); //随机
        }
    }

    第二种是在配置中定义规则(第一个值是服务名)

    user.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.BestAvailableRule //空闲连接规则

    常用的规则类型

    BestAvailableRule(空闲连接规则)

    for (Server server: serverList) {
        ServerStats serverStats = loadBalancerStats.getSingleServerStat(server);
        if (!serverStats.isCircuitBreakerTripped(currentTime)) {
            int concurrentConnections = serverStats.getActiveRequestsCount(currentTime);
            if (concurrentConnections < minimalConcurrentConnections) {
                minimalConcurrentConnections = concurrentConnections;
                chosen = server;
            }
        }
    }
    

    遍历所有实例,选出请求数最低的实例。

    RandomRule(随机规则 )

    生成随机数获取实例。

    RoundRobinRule(轮询规则)

    根据实例数 1-N全部轮询一遍,然后再重头开始。

    RetryRule(重试规则)

    实例请求时间超过maxRetryMillis(500ms)时则会返回null并进行下一次请求,重试最多会尝试10次。

    WeightedResponseTimeRule(时间权重规则)

    使用该规则时,WeightedResponseTimeRule内会启动一个线程DynamicServerWeightTask定期去更新每个实例的权重数,调用方法为maintainWeights。

    public void maintainWeights() {
        ILoadBalancer lb = getLoadBalancer();
        if (lb == null) {
            return;
        }
        
        if (!serverWeightAssignmentInProgress.compareAndSet(false,  true))  {
            return; 
        }
        
        try {
            logger.info("Weight adjusting job started");
            AbstractLoadBalancer nlb = (AbstractLoadBalancer) lb;
            LoadBalancerStats stats = nlb.getLoadBalancerStats();
            if (stats == null) {
                // no statistics, nothing to do
                return;
            }
            double totalResponseTime = 0;
            // 第一次遍历得到所有平均请求时间的合
            for (Server server : nlb.getAllServers()) {
                // this will automatically load the stats if not in cache
                ServerStats ss = stats.getSingleServerStat(server);
                totalResponseTime += ss.getResponseTimeAvg();
            }
            // weight for each server is (sum of responseTime of all servers - responseTime)
            // so that the longer the response time, the less the weight and the less likely to be chosen
            Double weightSoFar = 0.0;
            
            // 第二次遍历把之前计算的合减去本次的平均请求时间
            List<Double> finalWeights = new ArrayList<Double>();
            for (Server server : nlb.getAllServers()) {
                ServerStats ss = stats.getSingleServerStat(server);
                double weight = totalResponseTime - ss.getResponseTimeAvg();
                weightSoFar += weight;
                finalWeights.add(weightSoFar);   
            }//这里会把权重数放到全局变量accumulatedWeights中
            setWeights(finalWeights);
        } catch (Exception e) {
            logger.error("Error calculating server weights", e);
        } finally {
            serverWeightAssignmentInProgress.set(false);
        }
    
    }

    后面在调用choose的时候就会根据最大的权重数生成一个随机数,并遍历各实例的权重数,权重数大于随机数即选择该实例。

    double randomWeight = random.nextDouble() * maxTotalWeight;
    //maxTotalWeight是获取accumulatedWeights的最后一个权重数
    int n = 0;
    for (Double d : currentWeights) {
      if (d >= randomWeight) {
        serverIndex = n;
        break;
      } else {
        n++;
      }
    }
    server = allList.get(serverIndex);

    自定义规则

    创建一个类,实现IRule即可自定义规则

    public class MyRule implements IRule {
    
        private ILoadBalancer loadBalancer;
    
        @Override
        public Server choose(Object key) {
         //这里编写你规则的逻辑 List<Server> servers = loadBalancer.getAllServers(); return servers.get(0); } @Override public void setLoadBalancer(ILoadBalancer lb) { this.loadBalancer = lb; } @Override public ILoadBalancer getLoadBalancer() { return this.loadBalancer; } }
  • 相关阅读:
    史上最全HashMap红黑树解析
    使用httpClient 调用get,Post接口
    VS 安装resharper 后 无法进行UnitTest
    [转]大数据的高并发的数据库优化
    【转】2019年7月份,阿里最新Java高频面试真题汇总
    【转】Apache的架构师们遵循的30条设计原则
    B树索引最通俗易懂的介绍
    spring Boot 学习(八、Spring Boot与与监控管理)
    spring Boot 学习(七、Spring Boot与开发热部署)
    vs快捷键
  • 原文地址:https://www.cnblogs.com/nicori/p/11672030.html
Copyright © 2020-2023  润新知