Ribbon的权重负载均衡策略

本文介绍了一种基于服务器响应时间的负载均衡策略——加权响应时间规则(WeightedResponseTimeRule)。该策略通过计算各服务器的响应时间来动态调整其权重,响应时间越短的服务器获得的权重越高,从而提高其被选中的概率。文章详细解析了其核心组件及工作流程,包括初始化过程、定时任务设置、服务器权重计算方法等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

WeightedResponseTimeRule根据每个服务器的响应时间计算权重,根据这里得出的权重来选择服务器,相应时间越短的服务器被选择的概率越大。

void initialize(ILoadBalancer lb) {        
    if (serverWeightTimer != null) {
        serverWeightTimer.cancel();
    }
    serverWeightTimer = new Timer("NFLoadBalancer-serverWeightTimer-"
            + name, true);
    serverWeightTimer.schedule(new DynamicServerWeightTask(), 0,
            serverWeightTaskTimerInterval);
    // do a initial run
    ServerWeight sw = new ServerWeight();
    sw.maintainWeights();

    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
        public void run() {
            logger
                    .info("Stopping NFLoadBalancer-serverWeightTimer-"
                            + name);
            serverWeightTimer.cancel();
        }
    }));
}

在其initialize()方法中,构造一个定时任务,默认调用的时间间隔为30秒,调度的具体任务为DynamicServerWeightTask。其中的行为很简单,只是通过构造一个ServerWeight来调用maintainWeights()方法来重新计算各个服务器的权重,来方便需要负载均衡的时候根据最新计算得到的权重来达到目的。

class DynamicServerWeightTask extends TimerTask {
    public void run() {
        ServerWeight serverWeight = new ServerWeight();
        try {
            serverWeight.maintainWeights();
        } catch (Throwable t) {
            logger.error(
                    "Throwable caught while running DynamicServerWeightTask for "
                            + name, t);
        }
    }
}

 

而在定时任务设置完毕之后,也会同时构造一个ServerWeight来调用maintainWeights()。

 

class ServerWeight {

    public void maintainWeights() {
        ILoadBalancer lb = getLoadBalancer();
        if (lb == null) {
            return;
        }
        if (serverWeightAssignmentInProgress.get()) {
            return; // Ping in progress - nothing to do
        } else {
            serverWeightAssignmentInProgress.set(true);
        }
        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;
            // find maximal 95% response time
            for (Server server : nlb.getServerList(false)) {
                // 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;
            
            // create new list and hot swap the reference
            List<Double> finalWeights = new ArrayList<Double>();
            for (Server server : nlb.getServerList(false)) {
                ServerStats ss = stats.getSingleServerStat(server);
                double weight = totalResponseTime - ss.getResponseTimeAvg();
                weightSoFar += weight;
                finalWeights.add(weightSoFar);   
            }
            setWeights(finalWeights);
        } catch (Throwable t) {
            logger.error("Exception while dynamically calculating server weights", t);
        } finally {
            serverWeightAssignmentInProgress.set(false);
        }

    }
}

 

首先,保证权重计算的线程安全,也就是同一时间只能有一个正在计算权重的任务。

 

这里通过一个AtomicBoolean来作为信号量来保证本次任务在当前时间的唯一性。

接下来遍历所有的服务器列表,得到每一个服务器之前的平均答复时间,并依次相加,得到所有服务器平均响应时间的总和。

在得到时间的总和之后,之后会得到一个大小为服务器列表中服务器个数为大小的数组,首先再次遍历所有的服务器,通过之前的平均响应时间之和减去该服务器的平均响应时间作为权重,之后加上之前所有的权重之和,记录在之前生成的数组的相应位置。在遍历完所有服务器之后,将得到的数组保存下来,作为一次权重计算下来的结果。

 

在通过choose()方法得到相应的服务器的时候就相应的简单的多。

double randomWeight = random.nextDouble() * maxTotalWeight;
// pick the server index based on the randomIndex
int n = 0;
for (Double d : currentWeights) {
    if (d >= randomWeight) {
        serverIndex = n;
        break;
    } else {
        n++;
    }
}

server = allList.get(serverIndex);

 

在刚才的数组中,权重值得总和也就是数组中的最后一位,直接得到一个介于0到这个总和的一个随机数,在之前得到的权重数组得到第一个大于该随机数的位置的下标,也就是选择的服务器,返回。

 

由于相应时间越短的服务器权重越大,与前一位的差也越大,随机数命中的概率也越大。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值