Skip to content

Commit 6edfb1d

Browse files
carryxyhzonghaishang
authored andcommitted
Optimize leastActiveSelect and weight test case (#2172)
* 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. * weight test for all the loadBalance. * optimize typo * optimize unit test
1 parent 733a376 commit 6edfb1d

File tree

5 files changed

+156
-13
lines changed

5 files changed

+156
-13
lines changed

dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
*/
1717
package org.apache.dubbo.rpc.cluster.loadbalance;
1818

19-
import org.apache.dubbo.common.Constants;
2019
import org.apache.dubbo.common.URL;
2120
import org.apache.dubbo.rpc.Invocation;
2221
import org.apache.dubbo.rpc.Invoker;
@@ -27,7 +26,6 @@
2726

2827
/**
2928
* LeastActiveLoadBalance
30-
*
3129
*/
3230
public class LeastActiveLoadBalance extends AbstractLoadBalance {
3331

@@ -39,26 +37,26 @@ protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation
3937
int leastActive = -1; // The least active value of all invokers
4038
int leastCount = 0; // The number of invokers having the same least active value (leastActive)
4139
int[] leastIndexes = new int[length]; // The index of invokers having the same least active value (leastActive)
42-
int totalWeight = 0; // The sum of weights
40+
int totalWeight = 0; // The sum of with warmup weights
4341
int firstWeight = 0; // Initial value, used for comparision
4442
boolean sameWeight = true; // Every invoker has the same weight value?
4543
for (int i = 0; i < length; i++) {
4644
Invoker<T> invoker = invokers.get(i);
4745
int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive(); // Active number
48-
int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); // Weight
46+
int afterWarmup = getWeight(invoker, invocation);
4947
if (leastActive == -1 || active < leastActive) { // Restart, when find a invoker having smaller least active value.
5048
leastActive = active; // Record the current least active value
5149
leastCount = 1; // Reset leastCount, count again based on current leastCount
5250
leastIndexes[0] = i; // Reset
53-
totalWeight = weight; // Reset
54-
firstWeight = weight; // Record the weight the first invoker
51+
totalWeight = afterWarmup; // Reset
52+
firstWeight = afterWarmup; // Record the weight the first invoker
5553
sameWeight = true; // Reset, every invoker has the same weight value?
5654
} else if (active == leastActive) { // If current invoker's active value equals with leaseActive, then accumulating.
5755
leastIndexes[leastCount++] = i; // Record index number of this invoker
58-
totalWeight += weight; // Add this invoker's weight to totalWeight.
56+
totalWeight += afterWarmup; // Add this invoker's with warmup weight to totalWeight.
5957
// If every invoker has the same weight?
6058
if (sameWeight && i > 0
61-
&& weight != firstWeight) {
59+
&& afterWarmup != firstWeight) {
6260
sameWeight = false;
6361
}
6462
}
@@ -70,7 +68,7 @@ protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation
7068
}
7169
if (!sameWeight && totalWeight > 0) {
7270
// If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight.
73-
int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight);
71+
int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight) + 1;
7472
// Return a invoker based on the random value.
7573
for (int i = 0; i < leastCount; i++) {
7674
int leastIndex = leastIndexes[i];

dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveBalanceTest.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.apache.dubbo.rpc.cluster.loadbalance;
1818

1919
import org.apache.dubbo.rpc.Invoker;
20-
2120
import org.junit.Assert;
2221
import org.junit.Ignore;
2322
import org.junit.Test;
@@ -39,4 +38,31 @@ public void testLeastActiveLoadBalance_select() {
3938
}
4039
}
4140

41+
@Test
42+
public void testSelectByWeight() {
43+
int sumInvoker1 = 0;
44+
int sumInvoker2 = 0;
45+
int loop = 10000;
46+
47+
LeastActiveLoadBalance lb = new LeastActiveLoadBalance();
48+
for (int i = 0; i < loop; i++) {
49+
Invoker selected = lb.select(weightInvokers, null, weightTestInvocation);
50+
51+
if (selected.getUrl().getProtocol().equals("test1")) {
52+
sumInvoker1++;
53+
}
54+
55+
if (selected.getUrl().getProtocol().equals("test2")) {
56+
sumInvoker2++;
57+
}
58+
// never select invoker3 because it's active is more than invoker1 and invoker2
59+
Assert.assertTrue("select is not the least active one", !selected.getUrl().getProtocol().equals("test3"));
60+
}
61+
62+
// the sumInvoker1 : sumInvoker2 approximately equal to 1: 9
63+
System.out.println(sumInvoker1);
64+
System.out.println(sumInvoker2);
65+
66+
Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2, loop);
67+
}
4268
}

dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@
2121
import org.apache.dubbo.common.extension.ExtensionLoader;
2222
import org.apache.dubbo.rpc.Invocation;
2323
import org.apache.dubbo.rpc.Invoker;
24+
import org.apache.dubbo.rpc.RpcInvocation;
25+
import org.apache.dubbo.rpc.RpcStatus;
2426
import org.apache.dubbo.rpc.cluster.LoadBalance;
25-
2627
import org.junit.Assert;
2728
import org.junit.Before;
2829
import org.junit.BeforeClass;
@@ -50,6 +51,12 @@ public class LoadBalanceBaseTest {
5051
Invoker<LoadBalanceBaseTest> invoker4;
5152
Invoker<LoadBalanceBaseTest> invoker5;
5253

54+
RpcStatus weightTestRpcStatus1;
55+
RpcStatus weightTestRpcStatus2;
56+
RpcStatus weightTestRpcStatus3;
57+
58+
RpcInvocation weightTestInvocation;
59+
5360
/**
5461
* @throws java.lang.Exception
5562
*/
@@ -145,4 +152,55 @@ private static int calculateDefaultWarmupWeight(int uptime) {
145152
return AbstractLoadBalance.calculateWarmupWeight(uptime, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT);
146153
}
147154

155+
/*------------------------------------test invokers for weight---------------------------------------*/
156+
157+
protected List<Invoker<LoadBalanceBaseTest>> weightInvokers = new ArrayList<Invoker<LoadBalanceBaseTest>>();
158+
protected Invoker<LoadBalanceBaseTest> weightInvoker1;
159+
protected Invoker<LoadBalanceBaseTest> weightInvoker2;
160+
protected Invoker<LoadBalanceBaseTest> weightInvoker3;
161+
162+
@Before
163+
public void before() throws Exception {
164+
weightInvoker1 = mock(Invoker.class);
165+
weightInvoker2 = mock(Invoker.class);
166+
weightInvoker3 = mock(Invoker.class);
167+
168+
weightTestInvocation = new RpcInvocation();
169+
weightTestInvocation.setMethodName("test");
170+
171+
URL url1 = URL.valueOf("test1://0:1/DemoService");
172+
url1 = url1.addParameter(Constants.WEIGHT_KEY, 1);
173+
url1 = url1.addParameter(weightTestInvocation.getMethodName() + "." + Constants.WEIGHT_KEY, 1);
174+
url1 = url1.addParameter("active", 0);
175+
176+
URL url2 = URL.valueOf("test2://0:9/DemoService");
177+
url2 = url2.addParameter(Constants.WEIGHT_KEY, 9);
178+
url2 = url2.addParameter(weightTestInvocation.getMethodName() + "." + Constants.WEIGHT_KEY, 9);
179+
url2 = url2.addParameter("active", 0);
180+
181+
URL url3 = URL.valueOf("test3://1:6/DemoService");
182+
url3 = url3.addParameter(Constants.WEIGHT_KEY, 6);
183+
url3 = url3.addParameter(weightTestInvocation.getMethodName() + "." + Constants.WEIGHT_KEY, 6);
184+
url3 = url3.addParameter("active", 1);
185+
186+
given(weightInvoker1.isAvailable()).willReturn(true);
187+
given(weightInvoker1.getUrl()).willReturn(url1);
188+
189+
given(weightInvoker2.isAvailable()).willReturn(true);
190+
given(weightInvoker2.getUrl()).willReturn(url2);
191+
192+
given(weightInvoker3.isAvailable()).willReturn(true);
193+
given(weightInvoker3.getUrl()).willReturn(url3);
194+
195+
weightInvokers.add(weightInvoker1);
196+
weightInvokers.add(weightInvoker2);
197+
weightInvokers.add(weightInvoker3);
198+
199+
weightTestRpcStatus1 = RpcStatus.getStatus(weightInvoker1.getUrl(), weightTestInvocation.getMethodName());
200+
weightTestRpcStatus2 = RpcStatus.getStatus(weightInvoker2.getUrl(), weightTestInvocation.getMethodName());
201+
weightTestRpcStatus3 = RpcStatus.getStatus(weightInvoker3.getUrl(), weightTestInvocation.getMethodName());
202+
203+
// weightTestRpcStatus3 active is 1
204+
RpcStatus.beginCount(weightInvoker3.getUrl(), weightTestInvocation.getMethodName());
205+
}
148206
}

dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalanceTest.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import org.apache.dubbo.rpc.Invoker;
2020
import org.apache.dubbo.rpc.RpcStatus;
21-
2221
import org.junit.Assert;
2322
import org.junit.Test;
2423

@@ -54,4 +53,35 @@ public void testRandomLoadBalanceSelect() {
5453
Assert.assertEquals(0, counter.get(invoker5).intValue());
5554
}
5655

56+
@Test
57+
public void testSelectByWeight() {
58+
int sumInvoker1 = 0;
59+
int sumInvoker2 = 0;
60+
int sumInvoker3 = 0;
61+
int loop = 10000;
62+
63+
RandomLoadBalance lb = new RandomLoadBalance();
64+
for (int i = 0; i < loop; i++) {
65+
Invoker selected = lb.select(weightInvokers, null, weightTestInvocation);
66+
67+
if (selected.getUrl().getProtocol().equals("test1")) {
68+
sumInvoker1++;
69+
}
70+
71+
if (selected.getUrl().getProtocol().equals("test2")) {
72+
sumInvoker2++;
73+
}
74+
75+
if (selected.getUrl().getProtocol().equals("test3")) {
76+
sumInvoker3++;
77+
}
78+
}
79+
80+
// 1 : 9 : 6
81+
System.out.println(sumInvoker1);
82+
System.out.println(sumInvoker2);
83+
System.out.println(sumInvoker3);
84+
Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2 + sumInvoker3, loop);
85+
}
86+
5787
}

dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.apache.dubbo.rpc.cluster.loadbalance;
1818

1919
import org.apache.dubbo.rpc.Invoker;
20-
2120
import org.junit.Assert;
2221
import org.junit.Test;
2322

@@ -34,4 +33,36 @@ public void testRoundRobinLoadBalanceSelect() {
3433
Assert.assertTrue("abs diff should < 1", Math.abs(count - runs / (0f + invokers.size())) < 1f);
3534
}
3635
}
36+
37+
@Test
38+
public void testSelectByWeight() {
39+
int sumInvoker1 = 0;
40+
int sumInvoker2 = 0;
41+
int sumInvoker3 = 0;
42+
int loop = 10000;
43+
44+
RoundRobinLoadBalance lb = new RoundRobinLoadBalance();
45+
for (int i = 0; i < loop; i++) {
46+
Invoker selected = lb.select(weightInvokers, null, weightTestInvocation);
47+
48+
if (selected.getUrl().getProtocol().equals("test1")) {
49+
sumInvoker1++;
50+
}
51+
52+
if (selected.getUrl().getProtocol().equals("test2")) {
53+
sumInvoker2++;
54+
}
55+
56+
if (selected.getUrl().getProtocol().equals("test3")) {
57+
sumInvoker3++;
58+
}
59+
}
60+
61+
// 1 : 9 : 6
62+
System.out.println(sumInvoker1);
63+
System.out.println(sumInvoker2);
64+
System.out.println(sumInvoker3);
65+
Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2 + sumInvoker3, loop);
66+
}
67+
3768
}

0 commit comments

Comments
 (0)