权重轮询调度算法 java版本

权重轮询调度算法(Weighted Round-Robin Scheduling)--java版本

由于每台服务器的配置、安装的业务应用等不同,其处理能力会不一样。所以,我们根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。

2个java源文件,如下所示:

public interface IProduceStrategy {

    public int getPartitionIdForTopic();

}
public class WeightFactorProduceStrategy implements IProduceStrategy {
    private int i = -1; //表示上一次选择的服务器
    private int cw = 0; //表示当前调度的权值
    private int gcd = 0; //当前所有权重的最大公约数 比如 2,4,8 的最大公约数为:2
    private int maxWeight;

    private List<Integer> weights = null;  //作用计算最大公约数
    private PartitionWeightRRParameter weightRRParametersDns[] = null;

    /**
     *  按照轮询调研权重配置,格式如下:partition1:weight,partition2:weight
     * @param partConfig
     */
    public WeightFactorProduceStrategy(String partConfig) {
        validate(partConfig);
        this.initWeigthParam(Tools.parseCsvMap(partConfig));
    }

    private Pattern pattern = Pattern.compile("([\\d+\\:\\d+],?){1,}");

    private void validate(String partConfig) {
        if (partConfig.length() <= 0)
            throw new InvalidPartitonConfigException("partition config is incorrect :" + partConfig);
        else if (partConfig.equals(".") || partConfig.equals(".."))
            throw new InvalidPartitonConfigException("partition config is incorrect :" + partConfig);

        Matcher matcher = pattern.matcher(partConfig);
        if(matcher.find()) {
            String rexStr = matcher.group();
            if (!rexStr.equals(partConfig))
                throw new InvalidPartitonConfigException("partition config is incorrect :" + partConfig);
        } else {
            throw new InvalidPartitonConfigException("partition config is incorrect :" + partConfig);
        }
    }

    /**
     * 格式如下:partition1:weight,partition2:weight
     * @param csvMap
     */
    private void initWeigthParam(Map<String, String> csvMap) {
        weightRRParametersDns = new PartitionWeightRRParameter[csvMap.size()];
        int numPart = 0;
        weights = new ArrayList<Integer>(csvMap.size());
        Set<Map.Entry<String, String>> entrySet = csvMap.entrySet();
        for(Iterator<Map.Entry<String, String>> its = entrySet.iterator(); its.hasNext(); ) {
            Map.Entry<String, String> entry = its.next();
            weights.add(Integer.valueOf(entry.getValue()));
            weightRRParametersDns[numPart++] = new PartitionWeightRRParameter(Integer.valueOf(entry.getKey()), Integer.valueOf(entry.getValue()));
        }

        gcd = getGcdByList(weights);
        maxWeight = getMaxWeight();
    }

    /**
     * 计算最大公约数
     * @param weight_m 权重数
     * @param weight_n 权重数
     * @return
     */
    private int GCD(int weight_m,int weight_n)
    {
        int temp;
        while(weight_n != 0){
            if(weight_m < weight_n){
                temp = weight_m;
                weight_m = weight_n;
                weight_n = temp;
            }
            temp = weight_m - weight_n;
            weight_m = weight_n;
            weight_n = temp;
        }
        return weight_m;
    }

    /**
     *
     * @param weights      权重列表
     * @param startIndex   list索引值,起始位置。
     * @param nextGcd      传入最大公约数
     * @return
     */
    private int getGcdByList(List<Integer> weights, int startIndex, int nextGcd) {
        if ( weights.size() < 2) {
            throw new IllegalArgumentException("At least a number of parameters for 2");
        }
        if (weights.size() == 2 && startIndex == 0) {
            return this.GCD(weights.get(startIndex), weights.get(startIndex + 1));
        }

        if (startIndex + 1 > weights.size() -1 )
            return nextGcd;
        int curGcd = nextGcd > 0 ? nextGcd : weights.get(startIndex);
        int nextIndex = startIndex + 1;
        nextGcd = GCD(curGcd, weights.get(startIndex + 1));              //0,1

        return getGcdByList(weights, nextIndex, nextGcd);
    }

    private int getGcdByList(List<Integer> weights) {
        return this.getGcdByList(weights, 0, 0);
    }

    private int getWeightDns() {
        for ( ; ; ) {
            i = (i + 1) % weightRRParametersDns.length;
            if (i == 0) {
                cw = cw - gcd;  //表示当前调度的权值
                if (cw <= 0) {
                    cw = maxWeight;
                    if (cw == 0) {
                        return 0;
                    }
                }
            }

            if (weightRRParametersDns[i].getWeight() >= cw ) {
                return weightRRParametersDns[i].getPartition();
            }
        }
    }

    private int getMaxWeight() {
        int max = 0;
        for (int i = 0; i< weightRRParametersDns.length;i++) {
            if (weightRRParametersDns[i].getWeight() >= max) {
                max = weightRRParametersDns[i].getWeight();
            }
        }

        return max;
    }

    public int getPartitionIdForTopic() {
        return this.getWeightDns();
    }

    /**
     * 分区权重参数类
     */
    static class PartitionWeightRRParameter {
        private int partition;
        private int weight;

        public PartitionWeightRRParameter(int partition, int weight) {
            this.partition = partition;
            this.weight = weight;
        }

        public int getPartition() {
            return partition;
        }

        public int getWeight() {
            return weight;
        }
    }

}

单元测试类:

public class WeightFactorProduceStrategyTest {

    @Test
    public void testGetPartitionIdForTopic() throws Exception {
        IProduceStrategy weightFcProStrategy = new WeightFactorProduceStrategy("0:5,1:15,2:20");

        for (int i = 0; i < 40; i++) {
//            weightFcProStrategy.getPartitionIdForTopic();
            System.out.println(weightFcProStrategy.getPartitionIdForTopic());
        }
    }
}

测试结果如下:

2
2
1
2
1
2
1
0
2
2
1
2
1
2
1
0
2
2
1
2
1
2
1
0
2
2
1
2
1
2
1
0
2
2
1
2
1
2
1
0

权重轮询调度算法 java版本,布布扣,bubuko.com

时间: 2024-12-16 06:20:35

权重轮询调度算法 java版本的相关文章

权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现

1 import java.math.BigInteger; 2 import java.util.ArrayList; 3 import java.util.HashMap; 4 import java.util.List; 5 import java.util.Map; 6 import java.util.Map.Entry; 7 8 /** 9 * 权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现 10 * @author huligong 1

权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现2

权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现 ----参考Nginx中负载均衡算法实现 与上一遍博客 http://www.cnblogs.com/huligong1234/p/3819979.html 中实现方式不同,这里主要参考这篇文章的实现: Nginx 负载均衡-加权轮询策略剖析 http://www.cnblogs.com/dyllove98/archive/2013/07/13/3188450.html,与上一遍中实现比起来,效果比较好

golang实现权重轮询调度算法

package main import ( "fmt" "time" ) var slaveDns = map[int]map[string]interface{}{ 0: {"connectstring": "[email protected](172.16.0.164:3306)/shiqu_tools?charset=utf8", "weight": 2}, 1: {"connectstri

轮询算法

在多台机器实现负载均衡的时候,经常用到轮询调度算法(Round-Robin Scheduling). 轮询调度算法就是以循环的方式依次将请求调度不同的服务器,即每次调度执行i = (i + 1) mod n,并选出第i台服务器. 算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度. 1.算法流程:假设有一组服务器 S = {S0, S1, -, Sn-1} ,有相应的权重,变量i表示上次选择的服务器,权值cw初始化为0,i初始化为-1 ,当第一次的时候取权值取最大的那个服

Nginx的继续深入(日志轮询切割,重写,负载均衡等)

Nginx的访问日志轮询切割 通常什么情况Nginx会把所有的访问日志生成到一个制定的访问日志文件access.log里面,但时间一长,日志个头很大不利于日志的分析和处理. 有必要对Nginx日志进行按天或按小时进行切割,分成不同的文件保存. [[email protected] logs]#cat /server/script/cut_nginx_log.sh#!/bin/shDataformat = `date +%Y%m%d`Basedir = "/usr/local/nginx"

LVS负载均衡之IPVSADM命令说明与轮询解释

"1" IPVSADM常用参数说明:-A:在内核的虚拟服务器表中添加一条新的虚拟服务器记录-E:编辑内核虚拟服务器表中的一条虚拟服务器记录-D:删除内核虚拟服务器表中的一条虚拟服务器记录-C:清除内核虚拟服务器表中的所有记录-R:恢复虚拟服务器规则-S:保存虚拟服务器规则,输出为-R选项可读的格式-a:在内核虚拟服务器表的一条记录里添加一条新的真实服务器记录-e:编辑一条虚拟服务器记录中的某条真实服务器记录-d:删除一条虚拟服务器记录中的某条真实服务器记录-L|-l:显示内核虚拟服务器

java cache过期策略两种实现,一个基于list轮询一个基于timer定时

最近项目要引入缓存机制,但是不想引入分布式的缓存框架,所以自己就写了一个轻量级的缓存实现,有两个版本,一个是通过timer实现其超时过期处理,另外一个是通过list轮询.       首先要了解下java1.6中的ConcurrentMap ,他是一个线程安全的Map实现,特别说明的是在没有特别需求的情况下可以用ConcurrentHashMap.我是想学习一下读写锁的应用,就自己实现了一个SimpleConcurrentHashMap. [java] view plain copy print

JAVA多线程编中的轮询锁与定时锁

显示锁                                                                                     Lock接口是Java 5.0新增的接口,该接口的定义如下: 1 2 3 4 5 6 7 8 publicinterface Lock {     void lock();     void lockInterruptibly() throws InterruptedException;     boolean tryLo

java用while循环设计轮询线程的性能问题

java用while循环设计轮询线程的性能问题 轮询线程在开发过程中的应用是比较广泛的,在这我模拟一个场景,有一个队列和轮询线程,主线程往队列中入队消息,轮询线程循环从队列中读取消息并打印消息内容.有点类似Android中Handler发送消息. 首先定义一个Message类. public class Message { private String content; public Message(String content) { this.content=content; } public