From a42fb7f6393359c196b4e7967444c38b085ddf6b Mon Sep 17 00:00:00 2001 From: xiuyuhang <442367943@qq.com> Date: Thu, 2 Aug 2018 19:14:23 +0800 Subject: [PATCH 1/6] Now the select is select a random one when there are several least active invokers and all of them are in warm up. After this pr, it will select also by weight and warm up. And fix a bug when two invoker's active is same and weight not same. --- .../loadbalance/LeastActiveLoadBalance.java | 24 ++-- .../loadbalance/LeastActiveBalanceTest.java | 124 ++++++++++++++++++ 2 files changed, 135 insertions(+), 13 deletions(-) diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java index 956ff7709fb..501fa81ed3f 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java @@ -16,7 +16,6 @@ */ package org.apache.dubbo.rpc.cluster.loadbalance; -import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; @@ -27,7 +26,6 @@ /** * LeastActiveLoadBalance - * */ public class LeastActiveLoadBalance extends AbstractLoadBalance { @@ -39,26 +37,26 @@ protected Invoker doSelect(List> invokers, URL url, Invocation int leastActive = -1; // The least active value of all invokers int leastCount = 0; // The number of invokers having the same least active value (leastActive) int[] leastIndexes = new int[length]; // The index of invokers having the same least active value (leastActive) - int totalWeight = 0; // The sum of weights - int firstWeight = 0; // Initial value, used for comparision + int totalWeightAfterWarmUp = 0; // The sum of after warmup weights + int firstWeightAfterWarmUp = 0; // Initial value, used for comparision boolean sameWeight = true; // Every invoker has the same weight value? for (int i = 0; i < length; i++) { Invoker invoker = invokers.get(i); int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive(); // Active number - int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); // Weight + int afterWarmup = getWeight(invoker, invocation); if (leastActive == -1 || active < leastActive) { // Restart, when find a invoker having smaller least active value. leastActive = active; // Record the current least active value leastCount = 1; // Reset leastCount, count again based on current leastCount leastIndexes[0] = i; // Reset - totalWeight = weight; // Reset - firstWeight = weight; // Record the weight the first invoker + totalWeightAfterWarmUp = afterWarmup; // Reset + firstWeightAfterWarmUp = afterWarmup; // Record the weight the first invoker sameWeight = true; // Reset, every invoker has the same weight value? } else if (active == leastActive) { // If current invoker's active value equals with leaseActive, then accumulating. leastIndexes[leastCount++] = i; // Record index number of this invoker - totalWeight += weight; // Add this invoker's weight to totalWeight. + totalWeightAfterWarmUp += afterWarmup; // Add this invoker's after warmup weight to totalWeightAfterWarmUp. // If every invoker has the same weight? if (sameWeight && i > 0 - && weight != firstWeight) { + && afterWarmup != firstWeightAfterWarmUp) { sameWeight = false; } } @@ -68,9 +66,9 @@ protected Invoker doSelect(List> invokers, URL url, Invocation // If we got exactly one invoker having the least active value, return this invoker directly. return invokers.get(leastIndexes[0]); } - if (!sameWeight && totalWeight > 0) { - // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight. - int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight); + if (!sameWeight && totalWeightAfterWarmUp > 0) { + // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeightAfterWarmUp. + int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeightAfterWarmUp) + 1; // Return a invoker based on the random value. for (int i = 0; i < leastCount; i++) { int leastIndex = leastIndexes[i]; @@ -79,7 +77,7 @@ protected Invoker doSelect(List> invokers, URL url, Invocation return invokers.get(leastIndex); } } - // If all invokers have the same weight value or totalWeight=0, return evenly. + // If all invokers have the same weight value or totalWeightAfterWarmUp=0, return evenly. return invokers.get(leastIndexes[ThreadLocalRandom.current().nextInt(leastCount)]); } } diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java index fd151bcdb2f..65066797b04 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java @@ -16,15 +16,24 @@ */ package org.apache.dubbo.rpc.cluster.loadbalance; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.junit.Assert; +import org.junit.Before; import org.junit.Ignore; import org.junit.Test; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.Random; import java.util.concurrent.atomic.AtomicLong; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + public class LeastActiveBalanceTest extends LoadBalanceBaseTest { @Ignore @Test @@ -39,4 +48,119 @@ public void testLeastActiveLoadBalance_select() { } } + private List> invokers = new ArrayList>(); + private Invoker invoker1; + private Invoker invoker2; + + @Before + public void before() throws Exception { + invoker1 = mock(Invoker.class); + invoker2 = mock(Invoker.class); + invoker3 = mock(Invoker.class); + + URL url1 = URL.valueOf("test1://0:1/DemoService"); + URL url2 = URL.valueOf("test2://0:9/DemoService"); + URL url3 = URL.valueOf("test3://1:6/DemoService"); + + given(invoker1.isAvailable()).willReturn(true); + given(invoker1.getUrl()).willReturn(url1); + + given(invoker2.isAvailable()).willReturn(true); + given(invoker2.getUrl()).willReturn(url2); + + given(invoker3.isAvailable()).willReturn(true); + given(invoker3.getUrl()).willReturn(url3); + + invokers.add(invoker1); + invokers.add(invoker2); + invokers.add(invoker3); + } + + @Test + public void testSelect() { + int sumInvoker1 = 0; + int sumInvoker2 = 0; + for (int i = 0; i < 100000; i++) { + MyLeastActiveLoadBalance lb = new MyLeastActiveLoadBalance(); + Invoker selected = lb.select(invokers, null, null); + + if (selected.getUrl().getProtocol().equals("test1")) { + sumInvoker1++; + } + + if (selected.getUrl().getProtocol().equals("test2")) { + sumInvoker2++; + } + // never select invoker3 because it's active is more than invoker1 and invoker2 + Assert.assertTrue("select is not the least active one", !selected.getUrl().getProtocol().equals("test3")); + } + + // the sumInvoker1 : sumInvoker2 approximately equal to 1: 9 + System.out.println(sumInvoker1); + System.out.println(sumInvoker2); + } + + class MyLeastActiveLoadBalance extends AbstractLoadBalance { + + private final Random random = new Random(); + + @Override + protected Invoker doSelect(List> invokers, URL url, Invocation invocation) { + int length = invokers.size(); // Number of invokers + int leastActive = -1; // The least active value of all invokers + int leastCount = 0; // The number of invokers having the same least active value (leastActive) + int[] leastIndexs = new int[length]; // The index of invokers having the same least active value (leastActive) + int totalWeightAfterWarmUp = 0; // The sum of after warmup weights + int firstWeightAfterWarmUp = 0; // Initial value, used for comparision + boolean sameWeight = true; // Every invoker has the same weight value? + for (int i = 0; i < length; i++) { + Invoker invoker = invokers.get(i); + + // mock active is invoker's url.getHost + int active = Integer.valueOf(invoker.getUrl().getHost()); // Active number + + // mock weight is invoker's url.getPort + int afterWarmup = invoker.getUrl().getPort(); + + if (leastActive == -1 || active < leastActive) { // Restart, when find a invoker having smaller least active value. + leastActive = active; // Record the current least active value + leastCount = 1; // Reset leastCount, count again based on current leastCount + leastIndexs[0] = i; // Reset + totalWeightAfterWarmUp = afterWarmup; // Reset + firstWeightAfterWarmUp = afterWarmup; // Record the weight the first invoker + sameWeight = true; // Reset, every invoker has the same weight value? + } else if (active == leastActive) { // If current invoker's active value equals with leaseActive, then accumulating. + leastIndexs[leastCount++] = i; // Record index number of this invoker + totalWeightAfterWarmUp += afterWarmup; // Add this invoker's after warmup weight to totalWeightAfterWarmUp. + // If every invoker has the same weight? + if (sameWeight && i > 0 + && afterWarmup != firstWeightAfterWarmUp) { + sameWeight = false; + } + } + } + // assert(leastCount > 0) + if (leastCount == 1) { + // If we got exactly one invoker having the least active value, return this invoker directly. + return invokers.get(leastIndexs[0]); + } + if (!sameWeight && totalWeightAfterWarmUp > 0) { + // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeightAfterWarmUp. + int offsetWeight = random.nextInt(totalWeightAfterWarmUp) + 1; + // Return a invoker based on the random value. + for (int i = 0; i < leastCount; i++) { + int leastIndex = leastIndexs[i]; + + // mock weight is invoker's url.getPort + offsetWeight -= invokers.get(leastIndex).getUrl().getPort(); + if (offsetWeight <= 0) + return invokers.get(leastIndex); + } + // assert that at most loop 'leastCount' counts + Assert.assertTrue("leastCount is still > 0", leastCount < 0); + } + // If all invokers have the same weight value or totalWeightAfterWarmUp=0, return evenly. + return invokers.get(leastIndexs[random.nextInt(leastCount)]); + } + } } From 64a4ec00aaf0f15e13db5c5d4b0103e8c05dbb23 Mon Sep 17 00:00:00 2001 From: xiuyuhang <442367943@qq.com> Date: Fri, 3 Aug 2018 20:37:51 +0800 Subject: [PATCH 2/6] weight test for all the loadBalance. --- .../loadbalance/LeastActiveLoadBalance.java | 20 ++-- .../loadbalance/LeastActiveBalanceTest.java | 44 ++----- .../loadbalance/LoadBalanceBaseTest.java | 30 +++++ .../loadbalance/RandomLoadBalanceTest.java | 73 ++++++++++++ .../RoundRobinLoadBalanceTest.java | 110 ++++++++++++++++++ 5 files changed, 230 insertions(+), 47 deletions(-) diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java index 501fa81ed3f..cabe0ddc8df 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java @@ -37,8 +37,8 @@ protected Invoker doSelect(List> invokers, URL url, Invocation int leastActive = -1; // The least active value of all invokers int leastCount = 0; // The number of invokers having the same least active value (leastActive) int[] leastIndexes = new int[length]; // The index of invokers having the same least active value (leastActive) - int totalWeightAfterWarmUp = 0; // The sum of after warmup weights - int firstWeightAfterWarmUp = 0; // Initial value, used for comparision + int taotalWeightWithWarmUp = 0; // The sum of with warmup weights + int firstWeightWithWarmUp = 0; // Initial value, used for comparision boolean sameWeight = true; // Every invoker has the same weight value? for (int i = 0; i < length; i++) { Invoker invoker = invokers.get(i); @@ -48,15 +48,15 @@ protected Invoker doSelect(List> invokers, URL url, Invocation leastActive = active; // Record the current least active value leastCount = 1; // Reset leastCount, count again based on current leastCount leastIndexes[0] = i; // Reset - totalWeightAfterWarmUp = afterWarmup; // Reset - firstWeightAfterWarmUp = afterWarmup; // Record the weight the first invoker + taotalWeightWithWarmUp = afterWarmup; // Reset + firstWeightWithWarmUp = afterWarmup; // Record the weight the first invoker sameWeight = true; // Reset, every invoker has the same weight value? } else if (active == leastActive) { // If current invoker's active value equals with leaseActive, then accumulating. leastIndexes[leastCount++] = i; // Record index number of this invoker - totalWeightAfterWarmUp += afterWarmup; // Add this invoker's after warmup weight to totalWeightAfterWarmUp. + taotalWeightWithWarmUp += afterWarmup; // Add this invoker's with warmup weight to totalWeightWithWarmUp. // If every invoker has the same weight? if (sameWeight && i > 0 - && afterWarmup != firstWeightAfterWarmUp) { + && afterWarmup != firstWeightWithWarmUp) { sameWeight = false; } } @@ -66,9 +66,9 @@ protected Invoker doSelect(List> invokers, URL url, Invocation // If we got exactly one invoker having the least active value, return this invoker directly. return invokers.get(leastIndexes[0]); } - if (!sameWeight && totalWeightAfterWarmUp > 0) { - // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeightAfterWarmUp. - int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeightAfterWarmUp) + 1; + if (!sameWeight && taotalWeightWithWarmUp > 0) { + // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeightWithWarmUp. + int offsetWeight = ThreadLocalRandom.current().nextInt(taotalWeightWithWarmUp) + 1; // Return a invoker based on the random value. for (int i = 0; i < leastCount; i++) { int leastIndex = leastIndexes[i]; @@ -77,7 +77,7 @@ protected Invoker doSelect(List> invokers, URL url, Invocation return invokers.get(leastIndex); } } - // If all invokers have the same weight value or totalWeightAfterWarmUp=0, return evenly. + // If all invokers have the same weight value or totalWeightWithWarmUp=0, return evenly. return invokers.get(leastIndexes[ThreadLocalRandom.current().nextInt(leastCount)]); } } diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java index 65066797b04..da063a9c7b8 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java @@ -19,21 +19,15 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; - import org.junit.Assert; -import org.junit.Before; import org.junit.Ignore; import org.junit.Test; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Random; import java.util.concurrent.atomic.AtomicLong; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - public class LeastActiveBalanceTest extends LoadBalanceBaseTest { @Ignore @Test @@ -48,41 +42,15 @@ public void testLeastActiveLoadBalance_select() { } } - private List> invokers = new ArrayList>(); - private Invoker invoker1; - private Invoker invoker2; - - @Before - public void before() throws Exception { - invoker1 = mock(Invoker.class); - invoker2 = mock(Invoker.class); - invoker3 = mock(Invoker.class); - - URL url1 = URL.valueOf("test1://0:1/DemoService"); - URL url2 = URL.valueOf("test2://0:9/DemoService"); - URL url3 = URL.valueOf("test3://1:6/DemoService"); - - given(invoker1.isAvailable()).willReturn(true); - given(invoker1.getUrl()).willReturn(url1); - - given(invoker2.isAvailable()).willReturn(true); - given(invoker2.getUrl()).willReturn(url2); - - given(invoker3.isAvailable()).willReturn(true); - given(invoker3.getUrl()).willReturn(url3); - - invokers.add(invoker1); - invokers.add(invoker2); - invokers.add(invoker3); - } - @Test - public void testSelect() { + public void testSelectByWeight() { int sumInvoker1 = 0; int sumInvoker2 = 0; + int loop = 100000; + + MyLeastActiveLoadBalance lb = new MyLeastActiveLoadBalance(); for (int i = 0; i < 100000; i++) { - MyLeastActiveLoadBalance lb = new MyLeastActiveLoadBalance(); - Invoker selected = lb.select(invokers, null, null); + Invoker selected = lb.select(weightInvokers, null, null); if (selected.getUrl().getProtocol().equals("test1")) { sumInvoker1++; @@ -98,6 +66,8 @@ public void testSelect() { // the sumInvoker1 : sumInvoker2 approximately equal to 1: 9 System.out.println(sumInvoker1); System.out.println(sumInvoker2); + + Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2, loop); } class MyLeastActiveLoadBalance extends AbstractLoadBalance { diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java index 877631f56e5..0a8bf2a9c6b 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java @@ -145,4 +145,34 @@ private static int calculateDefaultWarmupWeight(int uptime) { return AbstractLoadBalance.calculateWarmupWeight(uptime, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT); } + /*------------------------------------test invokers for weight---------------------------------------*/ + + protected List> weightInvokers = new ArrayList>(); + protected Invoker weightInvoker1; + protected Invoker weightInvoker2; + protected Invoker weightInvoker3; + + @Before + public void before() throws Exception { + weightInvoker1 = mock(Invoker.class); + weightInvoker2 = mock(Invoker.class); + weightInvoker3 = mock(Invoker.class); + + URL url1 = URL.valueOf("test1://0:1/DemoService"); + URL url2 = URL.valueOf("test2://0:9/DemoService"); + URL url3 = URL.valueOf("test3://1:6/DemoService"); + + given(weightInvoker1.isAvailable()).willReturn(true); + given(weightInvoker1.getUrl()).willReturn(url1); + + given(weightInvoker2.isAvailable()).willReturn(true); + given(weightInvoker2.getUrl()).willReturn(url2); + + given(weightInvoker3.isAvailable()).willReturn(true); + given(weightInvoker3.getUrl()).willReturn(url3); + + weightInvokers.add(weightInvoker1); + weightInvokers.add(weightInvoker2); + weightInvokers.add(weightInvoker3); + } } \ No newline at end of file diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java index 3f20291d3dc..3008caf8d96 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java @@ -16,13 +16,17 @@ */ package org.apache.dubbo.rpc.cluster.loadbalance; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcStatus; import org.junit.Assert; import org.junit.Test; +import java.util.List; import java.util.Map; +import java.util.Random; import java.util.concurrent.atomic.AtomicLong; /** @@ -54,4 +58,73 @@ public void testRandomLoadBalanceSelect() { Assert.assertEquals(0, counter.get(invoker5).intValue()); } + @Test + public void testSelectByWeight() { + int sumInvoker1 = 0; + int sumInvoker2 = 0; + int sumInvoker3 = 0; + int loop = 100000; + + MyRandomLoadBalance lb = new MyRandomLoadBalance(); + for (int i = 0; i < loop; i++) { + Invoker selected = lb.select(weightInvokers, null, null); + + if (selected.getUrl().getProtocol().equals("test1")) { + sumInvoker1++; + } + + if (selected.getUrl().getProtocol().equals("test2")) { + sumInvoker2++; + } + + if (selected.getUrl().getProtocol().equals("test3")) { + sumInvoker3++; + } + } + + // 1 : 9 : 6 + System.out.println(sumInvoker1); + System.out.println(sumInvoker2); + System.out.println(sumInvoker3); + Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2 + sumInvoker3, loop); + } + + class MyRandomLoadBalance extends AbstractLoadBalance { + + public static final String NAME = "random"; + + private final Random random = new Random(); + + @Override + protected Invoker doSelect(List> invokers, URL url, Invocation invocation) { + int length = invokers.size(); // Number of invokers + int totalWeight = 0; // The sum of weights + boolean sameWeight = true; // Every invoker has the same weight? + for (int i = 0; i < length; i++) { + + // mock weight + int weight = invokers.get(i).getUrl().getPort(); + + totalWeight += weight; // Sum + if (sameWeight && i > 0 + && weight != invokers.get(i - 1).getUrl().getPort()) { + sameWeight = false; + } + } + if (totalWeight > 0 && !sameWeight) { + // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight. + int offset = random.nextInt(totalWeight); + // Return a invoker based on the random value. + for (int i = 0; i < length; i++) { + offset -= invokers.get(i).getUrl().getPort(); + if (offset < 0) { + return invokers.get(i); + } + } + } + // If all invokers have the same weight value or totalWeight=0, return evenly. + return invokers.get(random.nextInt(length)); + } + } + } diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java index f3ae3518740..4ab7dec142c 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java @@ -16,12 +16,19 @@ */ package org.apache.dubbo.rpc.cluster.loadbalance; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.AtomicPositiveInteger; +import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.junit.Assert; import org.junit.Test; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicLong; public class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest { @@ -34,4 +41,107 @@ public void testRoundRobinLoadBalanceSelect() { Assert.assertTrue("abs diff should < 1", Math.abs(count - runs / (0f + invokers.size())) < 1f); } } + + @Test + public void testSelectByWeight() { + int sumInvoker1 = 0; + int sumInvoker2 = 0; + int sumInvoker3 = 0; + int loop = 100000; + + MyRoundRobinLoadBalance lb = new MyRoundRobinLoadBalance(); + for (int i = 0; i < loop; i++) { + Invoker selected = lb.select(weightInvokers, null, null); + + if (selected.getUrl().getProtocol().equals("test1")) { + sumInvoker1++; + } + + if (selected.getUrl().getProtocol().equals("test2")) { + sumInvoker2++; + } + + if (selected.getUrl().getProtocol().equals("test3")) { + sumInvoker3++; + } + } + + // 1 : 9 : 6 + System.out.println(sumInvoker1); + System.out.println(sumInvoker2); + System.out.println(sumInvoker3); + Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2 + sumInvoker3, loop); + } + + class MyRoundRobinLoadBalance extends AbstractLoadBalance { + + public static final String NAME = "roundrobin"; + + private final ConcurrentMap sequences = new ConcurrentHashMap(); + + @Override + protected Invoker doSelect(List> invokers, URL url, Invocation invocation) { + String key = "method1"; + int length = invokers.size(); // Number of invokers + int maxWeight = 0; // The maximum weight + int minWeight = Integer.MAX_VALUE; // The minimum weight + final LinkedHashMap, IntegerWrapper> invokerToWeightMap = new LinkedHashMap, IntegerWrapper>(); + int weightSum = 0; + for (int i = 0; i < length; i++) { + + int weight = invokers.get(i).getUrl().getPort(); + + maxWeight = Math.max(maxWeight, weight); // Choose the maximum weight + minWeight = Math.min(minWeight, weight); // Choose the minimum weight + if (weight > 0) { + invokerToWeightMap.put(invokers.get(i), new IntegerWrapper(weight)); + weightSum += weight; + } + } + AtomicPositiveInteger sequence = sequences.get(key); + if (sequence == null) { + sequences.putIfAbsent(key, new AtomicPositiveInteger()); + sequence = sequences.get(key); + } + int currentSequence = sequence.getAndIncrement(); + if (maxWeight > 0 && minWeight < maxWeight) { + int mod = currentSequence % weightSum; + for (int i = 0; i < maxWeight; i++) { + for (Map.Entry, IntegerWrapper> each : invokerToWeightMap.entrySet()) { + final Invoker k = each.getKey(); + final IntegerWrapper v = each.getValue(); + if (mod == 0 && v.getValue() > 0) { + return k; + } + if (v.getValue() > 0) { + v.decrement(); + mod--; + } + } + } + } + // Round robin + return invokers.get(currentSequence % length); + } + + private final class IntegerWrapper { + private int value; + + public IntegerWrapper(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + public void decrement() { + this.value--; + } + } + } } From dfcba18101a41525b494f04633973b16294aea30 Mon Sep 17 00:00:00 2001 From: xiuyuhang <442367943@qq.com> Date: Thu, 16 Aug 2018 18:42:09 +0800 Subject: [PATCH 3/6] optimize typo --- .../loadbalance/LeastActiveLoadBalance.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java index cabe0ddc8df..573e8a1c863 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java @@ -37,8 +37,8 @@ protected Invoker doSelect(List> invokers, URL url, Invocation int leastActive = -1; // The least active value of all invokers int leastCount = 0; // The number of invokers having the same least active value (leastActive) int[] leastIndexes = new int[length]; // The index of invokers having the same least active value (leastActive) - int taotalWeightWithWarmUp = 0; // The sum of with warmup weights - int firstWeightWithWarmUp = 0; // Initial value, used for comparision + int totalWeight = 0; // The sum of with warmup weights + int firstWeight = 0; // Initial value, used for comparision boolean sameWeight = true; // Every invoker has the same weight value? for (int i = 0; i < length; i++) { Invoker invoker = invokers.get(i); @@ -48,15 +48,15 @@ protected Invoker doSelect(List> invokers, URL url, Invocation leastActive = active; // Record the current least active value leastCount = 1; // Reset leastCount, count again based on current leastCount leastIndexes[0] = i; // Reset - taotalWeightWithWarmUp = afterWarmup; // Reset - firstWeightWithWarmUp = afterWarmup; // Record the weight the first invoker + totalWeight = afterWarmup; // Reset + firstWeight = afterWarmup; // Record the weight the first invoker sameWeight = true; // Reset, every invoker has the same weight value? } else if (active == leastActive) { // If current invoker's active value equals with leaseActive, then accumulating. leastIndexes[leastCount++] = i; // Record index number of this invoker - taotalWeightWithWarmUp += afterWarmup; // Add this invoker's with warmup weight to totalWeightWithWarmUp. + totalWeight += afterWarmup; // Add this invoker's with warmup weight to totalWeight. // If every invoker has the same weight? if (sameWeight && i > 0 - && afterWarmup != firstWeightWithWarmUp) { + && afterWarmup != firstWeight) { sameWeight = false; } } @@ -66,9 +66,9 @@ protected Invoker doSelect(List> invokers, URL url, Invocation // If we got exactly one invoker having the least active value, return this invoker directly. return invokers.get(leastIndexes[0]); } - if (!sameWeight && taotalWeightWithWarmUp > 0) { - // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeightWithWarmUp. - int offsetWeight = ThreadLocalRandom.current().nextInt(taotalWeightWithWarmUp) + 1; + if (!sameWeight && totalWeight > 0) { + // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight. + int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight) + 1; // Return a invoker based on the random value. for (int i = 0; i < leastCount; i++) { int leastIndex = leastIndexes[i]; @@ -77,7 +77,7 @@ protected Invoker doSelect(List> invokers, URL url, Invocation return invokers.get(leastIndex); } } - // If all invokers have the same weight value or totalWeightWithWarmUp=0, return evenly. + // If all invokers have the same weight value or totalWeight=0, return evenly. return invokers.get(leastIndexes[ThreadLocalRandom.current().nextInt(leastCount)]); } } From a8dcb28e21ff1c5a2ae4a9fa766937b0fb055e6f Mon Sep 17 00:00:00 2001 From: xiuyuhang <442367943@qq.com> Date: Fri, 17 Aug 2018 15:54:16 +0800 Subject: [PATCH 4/6] optimize unit test --- .../cluster/loadbalance/LeastActiveBalanceTest.java | 12 ++++++------ .../rpc/cluster/loadbalance/LoadBalanceBaseTest.java | 6 ++++++ .../cluster/loadbalance/RandomLoadBalanceTest.java | 7 ++++--- .../loadbalance/RoundRobinLoadBalanceTest.java | 3 ++- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java index da063a9c7b8..a264a79a20f 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.rpc.cluster.loadbalance; +import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; @@ -86,11 +87,10 @@ protected Invoker doSelect(List> invokers, URL url, Invocation for (int i = 0; i < length; i++) { Invoker invoker = invokers.get(i); - // mock active is invoker's url.getHost - int active = Integer.valueOf(invoker.getUrl().getHost()); // Active number + // Active number + int active = invoker.getUrl().getParameter("active", Constants.DEFAULT_WEIGHT); - // mock weight is invoker's url.getPort - int afterWarmup = invoker.getUrl().getPort(); + int afterWarmup = invoker.getUrl().getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); if (leastActive == -1 || active < leastActive) { // Restart, when find a invoker having smaller least active value. leastActive = active; // Record the current least active value @@ -121,8 +121,8 @@ protected Invoker doSelect(List> invokers, URL url, Invocation for (int i = 0; i < leastCount; i++) { int leastIndex = leastIndexs[i]; - // mock weight is invoker's url.getPort - offsetWeight -= invokers.get(leastIndex).getUrl().getPort(); + offsetWeight -= invokers.get(leastIndex).getUrl().getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); + if (offsetWeight <= 0) return invokers.get(leastIndex); } diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java index 0a8bf2a9c6b..d7f5edcd66a 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java @@ -159,8 +159,14 @@ public void before() throws Exception { weightInvoker3 = mock(Invoker.class); URL url1 = URL.valueOf("test1://0:1/DemoService"); + url1 = url1.addParameter(Constants.WEIGHT_KEY, 1); + url1 = url1.addParameter("active", 0); URL url2 = URL.valueOf("test2://0:9/DemoService"); + url2 = url2.addParameter(Constants.WEIGHT_KEY, 9); + url2 = url2.addParameter("active", 0); URL url3 = URL.valueOf("test3://1:6/DemoService"); + url3 = url3.addParameter(Constants.WEIGHT_KEY, 6); + url3 = url3.addParameter("active", 1); given(weightInvoker1.isAvailable()).willReturn(true); given(weightInvoker1.getUrl()).willReturn(url1); diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java index 3008caf8d96..a295b31085a 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.rpc.cluster.loadbalance; +import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; @@ -103,11 +104,11 @@ protected Invoker doSelect(List> invokers, URL url, Invocation for (int i = 0; i < length; i++) { // mock weight - int weight = invokers.get(i).getUrl().getPort(); + int weight = invokers.get(i).getUrl().getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); totalWeight += weight; // Sum if (sameWeight && i > 0 - && weight != invokers.get(i - 1).getUrl().getPort()) { + && weight != invokers.get(i - 1).getUrl().getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT)) { sameWeight = false; } } @@ -116,7 +117,7 @@ protected Invoker doSelect(List> invokers, URL url, Invocation int offset = random.nextInt(totalWeight); // Return a invoker based on the random value. for (int i = 0; i < length; i++) { - offset -= invokers.get(i).getUrl().getPort(); + offset -= invokers.get(i).getUrl().getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); if (offset < 0) { return invokers.get(i); } diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java index 4ab7dec142c..d7df6cb248f 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.rpc.cluster.loadbalance; +import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.utils.AtomicPositiveInteger; import org.apache.dubbo.rpc.Invocation; @@ -89,7 +90,7 @@ protected Invoker doSelect(List> invokers, URL url, Invocation int weightSum = 0; for (int i = 0; i < length; i++) { - int weight = invokers.get(i).getUrl().getPort(); + int weight = invokers.get(i).getUrl().getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); maxWeight = Math.max(maxWeight, weight); // Choose the maximum weight minWeight = Math.min(minWeight, weight); // Choose the minimum weight From 37c927adb5bcb7d301b10384b6e39160320c953d Mon Sep 17 00:00:00 2001 From: xiuyuhang <442367943@qq.com> Date: Wed, 26 Sep 2018 18:41:06 +0800 Subject: [PATCH 5/6] Optimize unit test --- .../loadbalance/LeastActiveBalanceTest.java | 72 +--------------- .../loadbalance/LoadBalanceBaseTest.java | 24 +++++- .../loadbalance/RandomLoadBalanceTest.java | 48 +---------- .../RoundRobinLoadBalanceTest.java | 84 +------------------ 4 files changed, 29 insertions(+), 199 deletions(-) diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java index a264a79a20f..d849365ec4c 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java @@ -16,17 +16,12 @@ */ package org.apache.dubbo.rpc.cluster.loadbalance; -import org.apache.dubbo.common.Constants; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; -import java.util.List; import java.util.Map; -import java.util.Random; import java.util.concurrent.atomic.AtomicLong; public class LeastActiveBalanceTest extends LoadBalanceBaseTest { @@ -49,9 +44,9 @@ public void testSelectByWeight() { int sumInvoker2 = 0; int loop = 100000; - MyLeastActiveLoadBalance lb = new MyLeastActiveLoadBalance(); + LeastActiveLoadBalance lb = new LeastActiveLoadBalance(); for (int i = 0; i < 100000; i++) { - Invoker selected = lb.select(weightInvokers, null, null); + Invoker selected = lb.select(weightInvokers, null, weightTestInvocation); if (selected.getUrl().getProtocol().equals("test1")) { sumInvoker1++; @@ -70,67 +65,4 @@ public void testSelectByWeight() { Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2, loop); } - - class MyLeastActiveLoadBalance extends AbstractLoadBalance { - - private final Random random = new Random(); - - @Override - protected Invoker doSelect(List> invokers, URL url, Invocation invocation) { - int length = invokers.size(); // Number of invokers - int leastActive = -1; // The least active value of all invokers - int leastCount = 0; // The number of invokers having the same least active value (leastActive) - int[] leastIndexs = new int[length]; // The index of invokers having the same least active value (leastActive) - int totalWeightAfterWarmUp = 0; // The sum of after warmup weights - int firstWeightAfterWarmUp = 0; // Initial value, used for comparision - boolean sameWeight = true; // Every invoker has the same weight value? - for (int i = 0; i < length; i++) { - Invoker invoker = invokers.get(i); - - // Active number - int active = invoker.getUrl().getParameter("active", Constants.DEFAULT_WEIGHT); - - int afterWarmup = invoker.getUrl().getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); - - if (leastActive == -1 || active < leastActive) { // Restart, when find a invoker having smaller least active value. - leastActive = active; // Record the current least active value - leastCount = 1; // Reset leastCount, count again based on current leastCount - leastIndexs[0] = i; // Reset - totalWeightAfterWarmUp = afterWarmup; // Reset - firstWeightAfterWarmUp = afterWarmup; // Record the weight the first invoker - sameWeight = true; // Reset, every invoker has the same weight value? - } else if (active == leastActive) { // If current invoker's active value equals with leaseActive, then accumulating. - leastIndexs[leastCount++] = i; // Record index number of this invoker - totalWeightAfterWarmUp += afterWarmup; // Add this invoker's after warmup weight to totalWeightAfterWarmUp. - // If every invoker has the same weight? - if (sameWeight && i > 0 - && afterWarmup != firstWeightAfterWarmUp) { - sameWeight = false; - } - } - } - // assert(leastCount > 0) - if (leastCount == 1) { - // If we got exactly one invoker having the least active value, return this invoker directly. - return invokers.get(leastIndexs[0]); - } - if (!sameWeight && totalWeightAfterWarmUp > 0) { - // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeightAfterWarmUp. - int offsetWeight = random.nextInt(totalWeightAfterWarmUp) + 1; - // Return a invoker based on the random value. - for (int i = 0; i < leastCount; i++) { - int leastIndex = leastIndexs[i]; - - offsetWeight -= invokers.get(leastIndex).getUrl().getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); - - if (offsetWeight <= 0) - return invokers.get(leastIndex); - } - // assert that at most loop 'leastCount' counts - Assert.assertTrue("leastCount is still > 0", leastCount < 0); - } - // If all invokers have the same weight value or totalWeightAfterWarmUp=0, return evenly. - return invokers.get(leastIndexs[random.nextInt(leastCount)]); - } - } } diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java index d7f5edcd66a..f9db9aeca09 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java @@ -21,8 +21,9 @@ import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.RpcStatus; import org.apache.dubbo.rpc.cluster.LoadBalance; - import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @@ -50,6 +51,12 @@ public class LoadBalanceBaseTest { Invoker invoker4; Invoker invoker5; + RpcStatus weightTestRpcStatus1; + RpcStatus weightTestRpcStatus2; + RpcStatus weightTestRpcStatus3; + + RpcInvocation weightTestInvocation; + /** * @throws java.lang.Exception */ @@ -158,14 +165,22 @@ public void before() throws Exception { weightInvoker2 = mock(Invoker.class); weightInvoker3 = mock(Invoker.class); + weightTestInvocation = new RpcInvocation(); + weightTestInvocation.setMethodName("test"); + URL url1 = URL.valueOf("test1://0:1/DemoService"); url1 = url1.addParameter(Constants.WEIGHT_KEY, 1); + url1 = url1.addParameter(weightTestInvocation.getMethodName() + "." + Constants.WEIGHT_KEY, 1); url1 = url1.addParameter("active", 0); + URL url2 = URL.valueOf("test2://0:9/DemoService"); url2 = url2.addParameter(Constants.WEIGHT_KEY, 9); + url2 = url2.addParameter(weightTestInvocation.getMethodName() + "." + Constants.WEIGHT_KEY, 9); url2 = url2.addParameter("active", 0); + URL url3 = URL.valueOf("test3://1:6/DemoService"); url3 = url3.addParameter(Constants.WEIGHT_KEY, 6); + url3 = url3.addParameter(weightTestInvocation.getMethodName() + "." + Constants.WEIGHT_KEY, 6); url3 = url3.addParameter("active", 1); given(weightInvoker1.isAvailable()).willReturn(true); @@ -180,5 +195,12 @@ public void before() throws Exception { weightInvokers.add(weightInvoker1); weightInvokers.add(weightInvoker2); weightInvokers.add(weightInvoker3); + + weightTestRpcStatus1 = RpcStatus.getStatus(weightInvoker1.getUrl(), weightTestInvocation.getMethodName()); + weightTestRpcStatus2 = RpcStatus.getStatus(weightInvoker2.getUrl(), weightTestInvocation.getMethodName()); + weightTestRpcStatus3 = RpcStatus.getStatus(weightInvoker3.getUrl(), weightTestInvocation.getMethodName()); + + // weightTestRpcStatus3 active is 1 + RpcStatus.beginCount(weightInvoker3.getUrl(), weightTestInvocation.getMethodName()); } } \ No newline at end of file diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java index a295b31085a..348b0bf94ba 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java @@ -16,18 +16,12 @@ */ package org.apache.dubbo.rpc.cluster.loadbalance; -import org.apache.dubbo.common.Constants; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcStatus; - import org.junit.Assert; import org.junit.Test; -import java.util.List; import java.util.Map; -import java.util.Random; import java.util.concurrent.atomic.AtomicLong; /** @@ -66,9 +60,9 @@ public void testSelectByWeight() { int sumInvoker3 = 0; int loop = 100000; - MyRandomLoadBalance lb = new MyRandomLoadBalance(); + RandomLoadBalance lb = new RandomLoadBalance(); for (int i = 0; i < loop; i++) { - Invoker selected = lb.select(weightInvokers, null, null); + Invoker selected = lb.select(weightInvokers, null, weightTestInvocation); if (selected.getUrl().getProtocol().equals("test1")) { sumInvoker1++; @@ -90,42 +84,4 @@ public void testSelectByWeight() { Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2 + sumInvoker3, loop); } - class MyRandomLoadBalance extends AbstractLoadBalance { - - public static final String NAME = "random"; - - private final Random random = new Random(); - - @Override - protected Invoker doSelect(List> invokers, URL url, Invocation invocation) { - int length = invokers.size(); // Number of invokers - int totalWeight = 0; // The sum of weights - boolean sameWeight = true; // Every invoker has the same weight? - for (int i = 0; i < length; i++) { - - // mock weight - int weight = invokers.get(i).getUrl().getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); - - totalWeight += weight; // Sum - if (sameWeight && i > 0 - && weight != invokers.get(i - 1).getUrl().getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT)) { - sameWeight = false; - } - } - if (totalWeight > 0 && !sameWeight) { - // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight. - int offset = random.nextInt(totalWeight); - // Return a invoker based on the random value. - for (int i = 0; i < length; i++) { - offset -= invokers.get(i).getUrl().getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); - if (offset < 0) { - return invokers.get(i); - } - } - } - // If all invokers have the same weight value or totalWeight=0, return evenly. - return invokers.get(random.nextInt(length)); - } - } - } diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java index d7df6cb248f..9c9461b212f 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java @@ -16,20 +16,11 @@ */ package org.apache.dubbo.rpc.cluster.loadbalance; -import org.apache.dubbo.common.Constants; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.AtomicPositiveInteger; -import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; - import org.junit.Assert; import org.junit.Test; -import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicLong; public class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest { @@ -50,9 +41,9 @@ public void testSelectByWeight() { int sumInvoker3 = 0; int loop = 100000; - MyRoundRobinLoadBalance lb = new MyRoundRobinLoadBalance(); + RoundRobinLoadBalance lb = new RoundRobinLoadBalance(); for (int i = 0; i < loop; i++) { - Invoker selected = lb.select(weightInvokers, null, null); + Invoker selected = lb.select(weightInvokers, null, weightTestInvocation); if (selected.getUrl().getProtocol().equals("test1")) { sumInvoker1++; @@ -74,75 +65,4 @@ public void testSelectByWeight() { Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2 + sumInvoker3, loop); } - class MyRoundRobinLoadBalance extends AbstractLoadBalance { - - public static final String NAME = "roundrobin"; - - private final ConcurrentMap sequences = new ConcurrentHashMap(); - - @Override - protected Invoker doSelect(List> invokers, URL url, Invocation invocation) { - String key = "method1"; - int length = invokers.size(); // Number of invokers - int maxWeight = 0; // The maximum weight - int minWeight = Integer.MAX_VALUE; // The minimum weight - final LinkedHashMap, IntegerWrapper> invokerToWeightMap = new LinkedHashMap, IntegerWrapper>(); - int weightSum = 0; - for (int i = 0; i < length; i++) { - - int weight = invokers.get(i).getUrl().getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); - - maxWeight = Math.max(maxWeight, weight); // Choose the maximum weight - minWeight = Math.min(minWeight, weight); // Choose the minimum weight - if (weight > 0) { - invokerToWeightMap.put(invokers.get(i), new IntegerWrapper(weight)); - weightSum += weight; - } - } - AtomicPositiveInteger sequence = sequences.get(key); - if (sequence == null) { - sequences.putIfAbsent(key, new AtomicPositiveInteger()); - sequence = sequences.get(key); - } - int currentSequence = sequence.getAndIncrement(); - if (maxWeight > 0 && minWeight < maxWeight) { - int mod = currentSequence % weightSum; - for (int i = 0; i < maxWeight; i++) { - for (Map.Entry, IntegerWrapper> each : invokerToWeightMap.entrySet()) { - final Invoker k = each.getKey(); - final IntegerWrapper v = each.getValue(); - if (mod == 0 && v.getValue() > 0) { - return k; - } - if (v.getValue() > 0) { - v.decrement(); - mod--; - } - } - } - } - // Round robin - return invokers.get(currentSequence % length); - } - - private final class IntegerWrapper { - private int value; - - public IntegerWrapper(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } - - public void decrement() { - this.value--; - } - } - } } From cd05619b4528df7d883660d40d0b0103a2f530d4 Mon Sep 17 00:00:00 2001 From: xiuyuhang <442367943@qq.com> Date: Wed, 26 Sep 2018 19:14:16 +0800 Subject: [PATCH 6/6] Optimize unit test --- .../dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java | 4 ++-- .../dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java | 2 +- .../rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java index d849365ec4c..836994fdcc8 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java @@ -42,10 +42,10 @@ public void testLeastActiveLoadBalance_select() { public void testSelectByWeight() { int sumInvoker1 = 0; int sumInvoker2 = 0; - int loop = 100000; + int loop = 10000; LeastActiveLoadBalance lb = new LeastActiveLoadBalance(); - for (int i = 0; i < 100000; i++) { + for (int i = 0; i < loop; i++) { Invoker selected = lb.select(weightInvokers, null, weightTestInvocation); if (selected.getUrl().getProtocol().equals("test1")) { diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java index 348b0bf94ba..d31a85d08d4 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java @@ -58,7 +58,7 @@ public void testSelectByWeight() { int sumInvoker1 = 0; int sumInvoker2 = 0; int sumInvoker3 = 0; - int loop = 100000; + int loop = 10000; RandomLoadBalance lb = new RandomLoadBalance(); for (int i = 0; i < loop; i++) { diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java index 9c9461b212f..e10f69fea62 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java @@ -39,7 +39,7 @@ public void testSelectByWeight() { int sumInvoker1 = 0; int sumInvoker2 = 0; int sumInvoker3 = 0; - int loop = 100000; + int loop = 10000; RoundRobinLoadBalance lb = new RoundRobinLoadBalance(); for (int i = 0; i < loop; i++) {