赞
踩
有三个处理服务器A,B,C,权重比为2:3:5,要求根据权重比进行分配任务
根据权重比列,随机生成区间数量来分配,这种是相对概率,分配量不是百分百按权重来
实现方式:
新建一个数组,数组的大小是权重和或权重和的倍数,简单点我们直接设置大小为题目的2+3+5=10,数组中A,B,C的数量就是他们的权重比,2:3:5,既数组为[A,A,B,B,B,C,C,C,C,C],当然里面摆放位置可以调整(但是这种调整位置方式是否可以达到相对平滑分配的效果没试过),由在10内随机生成数作为索引值,来决定取数组中的哪个索引中的值,
因为数组内的每个服务器数量是按照权重来的,所以只要随机次数足够大,取得的服务器概率理论上是无限接近于权重比的。
加权轮询,分为两种。
(1)一种是普通的
保证任务总数内的任务是按权重比进行分配的,但是可能会导致大量的任务在短时间内分配给一台。比如10个任务,A分配2个,B分配3个,C分配5个,但是在顺序上可能C的5个在一起,然后前面5个任务全部给了C,A和B一个都没,只有当任务第六个的时候才会分配给A或B
可以通过调整数组A,B,C的位置让其分散些,如[A,B,C,A,B,C,B,C,C,C],可以让数组分配相对的均衡些。(个人推荐用这个)
实现方式:
就是生成一个大小为权重总和的服务器List,里面每个服务器的元素数量由权重值决定,每次获取索引都加一,如果满了就重置从0开始
(2)一种是平滑加权轮询
保证任务总数内的任务是按权重比进行分配的,且顺序上比较均衡,比如10个任务,A分配2个,B分配3个,C分配5个,第一个是C,第二个是B,第三个是A,再一直往下。
实现方式:
所谓权重,可以理解为能力大小不均衡,从数字角度来看,就是每次递增的大小不一,递减大小一样,那次操作每个服务器的【当前权重】都自增【权重值】(初始固定值),取当前权重最大的一个,被选中则当前权重要减去【权重总和】(初始固定值)。
import java.util.*; /** * 轮询接口实现类 * * @author ppp * @date 2022/6/21 */ public class WeightedRobinServiceImpl { private final List<ServerNode> serverNodeList; private int index; private final int weightTotal; public WeightedRobinServiceImpl(List<ServerNode> list) { this.index = 0; this.serverNodeList = list; this.weightTotal = list.stream().mapToInt(ServerNode::getWeight).sum(); } /** * 平滑加权选择 * * @return 服务器ip */ public synchronized String smoothSelectServer() { if (serverNodeList.isEmpty()) { return null; } ServerNode maxServerNode = serverNodeList.stream().max(Comparator.comparingInt(ServerNode::getCurrentWeight)).get(); serverNodeList.forEach(serverNode -> { / * 参考其它文章的话,节点还有一个偏移权重属性,初始值为权重值,这个偏移权重是用来实时调整服务器能力的, * 每次选举的时候,当前权重就要加上偏移权重,每次选择了这个服务器,但是这个服务器响应失败(比如请求堵塞、网络波动),那么就把他的偏移值减一 * 相反,选择这个服务器响应成功(说明服务器响应能力变好或至少没变差),那么他的偏移值就加1,但是不能超过权重值 * 我们这里测试模拟的肯定没有响应失败的情况,所以不要偏移权重字段,直接也是加的权重值(固定,标识响应能力一直不变) * / serverNode.setCurrentWeight(serverNode.getCurrentWeight() + serverNode.getWeight()); if (serverNode.equals(maxServerNode)) { serverNode.setCurrentWeight(serverNode.getCurrentWeight() - weightTotal); } }); return maxServerNode.getIp(); } /** * 普通加权选择 * * @return 服务器ip */ public synchronized String selectServer() { if (serverNodeList.isEmpty()) { return null; } List<String> nodeList = new ArrayList<>(); serverNodeList.forEach(serverNode -> { Integer weight = serverNode.getWeight(); for (int i = 0; i < weight; i++) { nodeList.add(serverNode.getIp()); } }); if (index >= nodeList.size()) { index = 0; } String s = nodeList.get(index); index++; return s; } /** * 随机加权选择 * * @return 服务器ip */ public synchronized String randomSelectServer() { if (serverNodeList.isEmpty()) { return null; } List<String> nodeList = new ArrayList<>(); serverNodeList.forEach(serverNode -> { Integer weight = serverNode.getWeight(); for (int i = 0; i < weight; i++) { nodeList.add(serverNode.getIp()); } }); Random random = new Random(); // 在权重范围内随机 int n = random.nextInt(weightTotal); return nodeList.get(n); } }
/** * 服务节点 * @author ppp * @date 2022/6/21 */ public class ServerNode { /** * 服务地址 */ private String ip; /** * 权重 */ private Integer weight; /** * 当前权重 */ private Integer currentWeight; public ServerNode(String ip, Integer weight) { this.ip = ip; this.weight = weight; this.currentWeight = weight; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public Integer getWeight() { return weight; } public void setWeight(Integer weight) { this.weight = weight; } public Integer getCurrentWeight() { return currentWeight; } public void setCurrentWeight(Integer currentWeight) { this.currentWeight = currentWeight; } @Override public String toString() { return "ServerNode{" + "ip='" + ip + '\'' + ", weight=" + weight + ", currentWeight=" + currentWeight + '}'; } }
@Test void weightedServiceTest() throws ExecutionException, InterruptedException { List<ServerNode> list = new ArrayList<>(); list.add(new ServerNode("192.168.0.1", 2)); list.add(new ServerNode("192.168.0.2", 3)); list.add(new ServerNode("192.168.0.3", 5)); WeightedRobinServiceImpl weightedRobinService = new WeightedRobinServiceImpl(list); ExecutorService executorService = Executors.newFixedThreadPool(10); List<String> arr = new ArrayList<>(); List<CompletableFuture<String>> threadArr = new ArrayList<>(); for (int i = 0; i < 10; i++) { CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> { // String s = weightedRobinService.randomSelectServer(); String s = weightedRobinService.selectServer(); System.out.println("线程" + Thread.currentThread().getName() + "获得了处理器: " + s); return s; }, executorService); threadArr.add(stringCompletableFuture); } threadArr.forEach(stringCompletableFuture -> { try { String s = stringCompletableFuture.get(); arr.add(s); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }); Map<String, Long> collect = arr.stream().collect(Collectors.groupingBy(s -> s, Collectors.counting())); collect.forEach((key, value) -> { System.out.println("处理服务器ip: " + key + ", 次数为:" + value); }); } @Test void weightedRobinServiceTest() { List<ServerNode> list = new ArrayList<>(); list.add(new ServerNode("192.168.0.1", 2)); list.add(new ServerNode("192.168.0.2", 3)); list.add(new ServerNode("192.168.0.3", 5)); WeightedRobinServiceImpl weightedRobinService = new WeightedRobinServiceImpl(list); Scanner scanner = new Scanner(System.in); while (true) { System.out.println("请输入需要处理的数量: "); if (scanner.hasNext()) { List<String> arr = new ArrayList<>(); int amount = scanner.nextInt(); for (int i = 0; i < amount; i++) { // String s = weightedRobinService.smoothSelectServer(); String s = weightedRobinService.selectServer(); // String s = weightedRobinService.randomSelectServer(); System.out.println(s); arr.add(s); } Map<String, Long> collect = arr.stream().collect(Collectors.groupingBy(s -> s, Collectors.counting())); collect.forEach((key, value) -> { System.out.println("处理服务器ip: " + key + ", 次数为:" + value); }); System.out.println("---------------------------------------------"); } } }
------------------平滑加权轮询--------------------------
结果是相对分散的
------------------普通加权--------------------------
他的结果是集中的
------------------随机加权--------------------------
参考:
https://blog.csdn.net/loveyour_1314/article/details/121781952
https://my.oschina.net/u/4047016/blog/4420117
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。