当前位置:   article > 正文

基于权重分配算法实现_java如何根据权重分配流量算法

java如何根据权重分配流量算法

一、在日常工作中,经常有一些针对资源分配的策略需要按权重设置,比如:某个rpc服务调用等等。今天聊一聊按权重分配资源的实现。

具体代码如下:

1.WeightRandom.java

  1. import lombok.Data;
  2. import java.io.Serializable;
  3. import java.util.*;
  4. import java.util.concurrent.atomic.AtomicInteger;
  5. public class WeightRandom {
  6. private Random random = new Random();
  7. private List<Resource> resources;
  8. private int factor;
  9. public void init() {
  10. this.resources = new ArrayList<Resource>();
  11. resources.add(new Resource("a", 30));
  12. resources.add(new Resource("b", 50));
  13. resources.add(new Resource("c", 1000));
  14. resources.add(new Resource("d", 100));
  15. // 初始化
  16. this.factor = 0;
  17. for (Resource resource:resources) {
  18. resource.setBegin(factor);
  19. factor += resource.getWeight();
  20. }
  21. }
  22. /**
  23. * 对比区间开始点
  24. * @return
  25. */
  26. public Resource random() {
  27. Resource selected = null;
  28. int rand = random.nextInt(factor);
  29. for (int i = resources.size() - 1; i >= 0; i--) {
  30. Resource resource = resources.get(i);
  31. if (rand >= resource.getBegin()) {
  32. selected = resource;
  33. break;
  34. }
  35. }
  36. return selected;
  37. }
  38. /**
  39. * 对比区间结束点
  40. * @return
  41. */
  42. public Resource randomX() {
  43. Resource selected = null;
  44. int rv = random.nextInt(factor);
  45. int endpoint = 0;//区间结束点
  46. for (Resource resource:resources) {
  47. endpoint+=resource.getWeight();
  48. if (rv<=endpoint) {
  49. selected = resource;
  50. break;
  51. }
  52. }
  53. return selected;
  54. }
  55. public static void main(String[] args) {
  56. Map<String, AtomicInteger> count = new HashMap<>(8);
  57. WeightRandom w = new WeightRandom();
  58. w.init();
  59. for (int i = 0; i < 10000; i++) {
  60. Resource resource = w.random();
  61. AtomicInteger ai = new AtomicInteger(0);
  62. AtomicInteger old = count.putIfAbsent(resource.getName(),ai);
  63. if(old==null){
  64. old=ai;
  65. }
  66. old.incrementAndGet();
  67. }
  68. System.out.println(count);
  69. System.out.println("=====chooseX=====");
  70. count.clear();
  71. for (int i = 0; i < 10000; i++) {
  72. Resource server = w.randomX();
  73. AtomicInteger ai = new AtomicInteger(0);
  74. AtomicInteger old = count.putIfAbsent(server.getName(),ai);
  75. if(old==null){
  76. old=ai;
  77. }
  78. old.incrementAndGet();
  79. }
  80. System.out.println(count);
  81. }
  82. @Data
  83. public static class Resource implements Serializable {
  84. private static final long serialVersionUID = -7447211367731992379L;
  85. private String name;
  86. private int weight;
  87. private int begin;
  88. public Resource(String name, int weigth) {
  89. this.name = name;
  90. this.weight = weigth;
  91. }
  92. }
  93. }

 

2.WeightRandomStrategy.java

  1. import org.apache.commons.lang3.tuple.ImmutablePair;
  2. import org.apache.commons.lang3.tuple.Pair;
  3. import java.util.*;
  4. import java.util.concurrent.atomic.AtomicInteger;
  5. /**
  6. * Java 基于权重按比例分配算法,对比区间结束点
  7. * @param <K>
  8. * @param <V>
  9. */
  10. public class WeightRandomStrategy<K, V extends Number> {
  11. private TreeMap<Double, K> weightMap = new TreeMap<>();
  12. public WeightRandomStrategy(List<Pair<K, V>> list) {
  13. for (Pair<K, V> pair : list) {
  14. double lastWeight = this.weightMap.size() == 0 ? 0 : this.weightMap.lastKey();
  15. this.weightMap.put(pair.getValue().doubleValue() + lastWeight, pair.getKey());
  16. }
  17. }
  18. /**
  19. * 依据权重返回 K
  20. * @return
  21. */
  22. public K random() {
  23. double randomWeight = this.weightMap.lastKey() * Math.random();
  24. SortedMap<Double, K> tailMap = this.weightMap.tailMap(randomWeight, false);
  25. return this.weightMap.get(tailMap.firstKey());
  26. }
  27. public static void main(String[] args) {
  28. List<Pair<String, Integer>> list = new ArrayList<>();
  29. list.add(new ImmutablePair<>("A", 90));
  30. list.add(new ImmutablePair<>("B", 10));
  31. list.add(new ImmutablePair<>("C", 30));
  32. list.add(new ImmutablePair<>("D", 200));
  33. WeightRandomStrategy<String, Integer> strategy = new WeightRandomStrategy<>(list);
  34. Map<String, AtomicInteger> count = new HashMap<>(8);
  35. for (int i = 0; i < 10000; i++) {
  36. String key=strategy.random();
  37. AtomicInteger ai = new AtomicInteger(0);
  38. AtomicInteger old = count.putIfAbsent(key,ai);
  39. if(old==null){
  40. old=ai;
  41. }
  42. old.incrementAndGet();
  43. }
  44. System.out.println(count);
  45. }
  46. }

 

3.WeightRandomStrategyX.java

  1. import org.apache.commons.lang3.tuple.ImmutablePair;
  2. import org.apache.commons.lang3.tuple.Pair;
  3. import java.util.*;
  4. import java.util.concurrent.ThreadLocalRandom;
  5. import java.util.concurrent.atomic.AtomicInteger;
  6. /**
  7. * Java 基于权重按比例分配算法,对比区间开始点
  8. * @param <K>
  9. * @param <V>
  10. */
  11. public class WeightRandomStrategyX<K, V extends Number> {
  12. private TreeMap<Double, K> weightMap = new TreeMap<>();
  13. private double factor=0D;
  14. public WeightRandomStrategyX(List<Pair<K, V>> list) {
  15. for (Pair<K, V> pair : list) {
  16. this.weightMap.put(factor, pair.getKey());
  17. this.factor+=pair.getValue().doubleValue();
  18. }
  19. }
  20. /**
  21. * 依据权重返回 K
  22. * @return
  23. */
  24. public K random() {
  25. double randomWeight = ThreadLocalRandom.current().nextDouble(factor);
  26. SortedMap<Double, K> tailMap = this.weightMap.headMap(randomWeight, false);
  27. return this.weightMap.get(tailMap.lastKey());
  28. }
  29. public static void main(String[] args) {
  30. List<Pair<String, Integer>> list = new ArrayList<>();
  31. list.add(new ImmutablePair<>("A", 90));
  32. list.add(new ImmutablePair<>("B", 10));
  33. list.add(new ImmutablePair<>("C", 30));
  34. list.add(new ImmutablePair<>("D", 200));
  35. WeightRandomStrategyX<String, Integer> strategy = new WeightRandomStrategyX<>(list);
  36. Map<String, AtomicInteger> count = new HashMap<>(8);
  37. for (int i = 0; i < 10000; i++) {
  38. String key=strategy.random();
  39. AtomicInteger ai = new AtomicInteger(0);
  40. AtomicInteger old = count.putIfAbsent(key,ai);
  41. if(old==null){
  42. old=ai;
  43. }
  44. old.incrementAndGet();
  45. }
  46. System.out.println(count);
  47. }
  48. }

其中WeightRandomStrategy的实现摘自https://dorole.com/2014/,是基于treeMap,非常巧妙!

注:以上实现若用于生产环境中需要做充分测试。

二、参考资料

https://dorole.com/2014/

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/289173
推荐阅读
相关标签
  

闽ICP备14008679号