Skip to content

Commit 28e1037

Browse files
authored
Optimize LeastActiveLoadBalance and add weight test case. (#2584)
1 parent 0ac21f0 commit 28e1037

File tree

2 files changed

+145
-26
lines changed

2 files changed

+145
-26
lines changed

dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java

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

19-
import com.alibaba.dubbo.common.Constants;
2019
import com.alibaba.dubbo.common.URL;
2120
import com.alibaba.dubbo.rpc.Invocation;
2221
import com.alibaba.dubbo.rpc.Invoker;
@@ -41,26 +40,26 @@ protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation
4140
int leastActive = -1; // The least active value of all invokers
4241
int leastCount = 0; // The number of invokers having the same least active value (leastActive)
4342
int[] leastIndexs = new int[length]; // The index of invokers having the same least active value (leastActive)
44-
int totalWeight = 0; // The sum of weights
43+
int totalWeight = 0; // The sum of with warmup weights
4544
int firstWeight = 0; // Initial value, used for comparision
4645
boolean sameWeight = true; // Every invoker has the same weight value?
4746
for (int i = 0; i < length; i++) {
4847
Invoker<T> invoker = invokers.get(i);
4948
int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive(); // Active number
50-
int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); // Weight
49+
int afterWarmup = getWeight(invoker, invocation); // Weight
5150
if (leastActive == -1 || active < leastActive) { // Restart, when find a invoker having smaller least active value.
5251
leastActive = active; // Record the current least active value
5352
leastCount = 1; // Reset leastCount, count again based on current leastCount
5453
leastIndexs[0] = i; // Reset
55-
totalWeight = weight; // Reset
56-
firstWeight = weight; // Record the weight the first invoker
54+
totalWeight = afterWarmup; // Reset
55+
firstWeight = afterWarmup; // Record the weight the first invoker
5756
sameWeight = true; // Reset, every invoker has the same weight value?
5857
} else if (active == leastActive) { // If current invoker's active value equals with leaseActive, then accumulating.
5958
leastIndexs[leastCount++] = i; // Record index number of this invoker
60-
totalWeight += weight; // Add this invoker's weight to totalWeight.
59+
totalWeight += afterWarmup; // Add this invoker's weight to totalWeight.
6160
// If every invoker has the same weight?
6261
if (sameWeight && i > 0
63-
&& weight != firstWeight) {
62+
&& afterWarmup != firstWeight) {
6463
sameWeight = false;
6564
}
6665
}
@@ -72,7 +71,7 @@ protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation
7271
}
7372
if (!sameWeight && totalWeight > 0) {
7473
// If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight.
75-
int offsetWeight = random.nextInt(totalWeight);
74+
int offsetWeight = random.nextInt(totalWeight) + 1;
7675
// Return a invoker based on the random value.
7776
for (int i = 0; i < leastCount; i++) {
7877
int leastIndex = leastIndexs[i];

dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/loadbalance/LoadBalanceTest.java

Lines changed: 138 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
import com.alibaba.dubbo.common.extension.ExtensionLoader;
2222
import com.alibaba.dubbo.rpc.Invocation;
2323
import com.alibaba.dubbo.rpc.Invoker;
24+
import com.alibaba.dubbo.rpc.RpcInvocation;
2425
import com.alibaba.dubbo.rpc.RpcStatus;
2526
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
26-
2727
import junit.framework.Assert;
2828
import org.junit.Before;
2929
import org.junit.BeforeClass;
@@ -40,7 +40,6 @@
4040

4141
/**
4242
* RoundRobinLoadBalanceTest
43-
*
4443
*/
4544
@SuppressWarnings({"unchecked", "rawtypes"})
4645
public class LoadBalanceTest {
@@ -52,6 +51,11 @@ public class LoadBalanceTest {
5251
Invoker<LoadBalanceTest> invoker4;
5352
Invoker<LoadBalanceTest> invoker5;
5453

54+
RpcStatus weightTestRpcStatus1;
55+
RpcStatus weightTestRpcStatus2;
56+
RpcStatus weightTestRpcStatus3;
57+
RpcInvocation weightTestInvocation;
58+
5559
/**
5660
* @throws java.lang.Exception
5761
*/
@@ -117,6 +121,81 @@ public void testRoundRobinLoadBalance_select() {
117121
}
118122
}
119123

124+
@Test
125+
public void testSelectByWeightLeastActive() {
126+
int sumInvoker1 = 0;
127+
int sumInvoker2 = 0;
128+
int loop = 10000;
129+
LeastActiveLoadBalance lb = new LeastActiveLoadBalance();
130+
for (int i = 0; i < loop; i++) {
131+
Invoker selected = lb.select(weightInvokers, null, weightTestInvocation);
132+
if (selected.getUrl().getProtocol().equals("test1")) {
133+
sumInvoker1++;
134+
}
135+
if (selected.getUrl().getProtocol().equals("test2")) {
136+
sumInvoker2++;
137+
}
138+
// never select invoker3 because it's active is more than invoker1 and invoker2
139+
Assert.assertTrue("select is not the least active one", !selected.getUrl().getProtocol().equals("test3"));
140+
}
141+
// the sumInvoker1 : sumInvoker2 approximately equal to 1: 9
142+
System.out.println(sumInvoker1);
143+
System.out.println(sumInvoker2);
144+
Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2, loop);
145+
}
146+
147+
@Test
148+
public void testSelectByWeightRandom() {
149+
int sumInvoker1 = 0;
150+
int sumInvoker2 = 0;
151+
int sumInvoker3 = 0;
152+
int loop = 10000;
153+
RandomLoadBalance lb = new RandomLoadBalance();
154+
for (int i = 0; i < loop; i++) {
155+
Invoker selected = lb.select(weightInvokers, null, weightTestInvocation);
156+
if (selected.getUrl().getProtocol().equals("test1")) {
157+
sumInvoker1++;
158+
}
159+
if (selected.getUrl().getProtocol().equals("test2")) {
160+
sumInvoker2++;
161+
}
162+
if (selected.getUrl().getProtocol().equals("test3")) {
163+
sumInvoker3++;
164+
}
165+
}
166+
// 1 : 9 : 6
167+
System.out.println(sumInvoker1);
168+
System.out.println(sumInvoker2);
169+
System.out.println(sumInvoker3);
170+
Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2 + sumInvoker3, loop);
171+
}
172+
173+
@Test
174+
public void testSelectByWeight() {
175+
int sumInvoker1 = 0;
176+
int sumInvoker2 = 0;
177+
int sumInvoker3 = 0;
178+
int loop = 10000;
179+
RoundRobinLoadBalance lb = new RoundRobinLoadBalance();
180+
for (int i = 0; i < loop; i++) {
181+
Invoker selected = lb.select(weightInvokers, null, weightTestInvocation);
182+
if (selected.getUrl().getProtocol().equals("test1")) {
183+
sumInvoker1++;
184+
}
185+
if (selected.getUrl().getProtocol().equals("test2")) {
186+
sumInvoker2++;
187+
}
188+
if (selected.getUrl().getProtocol().equals("test3")) {
189+
sumInvoker3++;
190+
}
191+
}
192+
// 1 : 9 : 6
193+
System.out.println(sumInvoker1);
194+
System.out.println(sumInvoker2);
195+
System.out.println(sumInvoker3);
196+
Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2 + sumInvoker3, loop);
197+
}
198+
120199
@Test
121200
public void testRandomLoadBalance_select() {
122201
int runs = 1000;
@@ -125,7 +204,7 @@ public void testRandomLoadBalance_select() {
125204
Long count = counter.get(minvoker).get();
126205
// System.out.println(count);
127206
Assert.assertTrue("abs diff shoud < avg",
128-
Math.abs(count - runs / (0f + invokers.size())) < runs / (0f + invokers.size()));
207+
Math.abs(count - runs / (0f + invokers.size())) < runs / (0f + invokers.size()));
129208
}
130209

131210
for (int i = 0; i < 5; i++) {
@@ -152,7 +231,7 @@ public void testLeastActiveLoadBalance_select() {
152231
Long count = counter.get(minvoker).get();
153232
// System.out.println(count);
154233
Assert.assertTrue("abs diff shoud < avg",
155-
Math.abs(count - runs / (0f + invokers.size())) < runs / (0f + invokers.size()));
234+
Math.abs(count - runs / (0f + invokers.size())) < runs / (0f + invokers.size()));
156235
}
157236
}
158237

@@ -172,33 +251,74 @@ public Map<Invoker, AtomicLong> getInvokeCounter(int runs, String loadbalanceNam
172251
@Test
173252
public void testLoadBalanceWarmup() {
174253
Assert.assertEquals(1,
175-
AbstractLoadBalance.calculateWarmupWeight(0, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
254+
AbstractLoadBalance.calculateWarmupWeight(0, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
176255
Assert.assertEquals(1,
177-
AbstractLoadBalance.calculateWarmupWeight(13, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
256+
AbstractLoadBalance.calculateWarmupWeight(13, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
178257
Assert.assertEquals(1,
179-
AbstractLoadBalance.calculateWarmupWeight(6 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
258+
AbstractLoadBalance.calculateWarmupWeight(6 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
180259
Assert.assertEquals(2,
181-
AbstractLoadBalance.calculateWarmupWeight(12 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
260+
AbstractLoadBalance.calculateWarmupWeight(12 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
182261
Assert.assertEquals(10,
183-
AbstractLoadBalance.calculateWarmupWeight(60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
262+
AbstractLoadBalance.calculateWarmupWeight(60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
184263
Assert.assertEquals(50, AbstractLoadBalance
185-
.calculateWarmupWeight(5 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
264+
.calculateWarmupWeight(5 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
186265
Assert.assertEquals(50, AbstractLoadBalance
187-
.calculateWarmupWeight(5 * 60 * 1000 + 23, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
266+
.calculateWarmupWeight(5 * 60 * 1000 + 23, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
188267
Assert.assertEquals(50, AbstractLoadBalance
189-
.calculateWarmupWeight(5 * 60 * 1000 + 5999, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
268+
.calculateWarmupWeight(5 * 60 * 1000 + 5999, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
190269
Assert.assertEquals(51, AbstractLoadBalance
191-
.calculateWarmupWeight(5 * 60 * 1000 + 6000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
270+
.calculateWarmupWeight(5 * 60 * 1000 + 6000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
192271
Assert.assertEquals(90, AbstractLoadBalance
193-
.calculateWarmupWeight(9 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
272+
.calculateWarmupWeight(9 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
194273
Assert.assertEquals(98, AbstractLoadBalance
195-
.calculateWarmupWeight(10 * 60 * 1000 - 12 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
274+
.calculateWarmupWeight(10 * 60 * 1000 - 12 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
196275
Assert.assertEquals(99, AbstractLoadBalance
197-
.calculateWarmupWeight(10 * 60 * 1000 - 6 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
276+
.calculateWarmupWeight(10 * 60 * 1000 - 6 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
198277
Assert.assertEquals(100, AbstractLoadBalance
199-
.calculateWarmupWeight(10 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
278+
.calculateWarmupWeight(10 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
200279
Assert.assertEquals(100, AbstractLoadBalance
201-
.calculateWarmupWeight(20 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
280+
.calculateWarmupWeight(20 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
202281
}
203282

283+
/*------------------------------------test invokers for weight---------------------------------------*/
284+
285+
protected List<Invoker<LoadBalanceTest>> weightInvokers = new ArrayList<Invoker<LoadBalanceTest>>();
286+
protected Invoker<LoadBalanceTest> weightInvoker1;
287+
protected Invoker<LoadBalanceTest> weightInvoker2;
288+
protected Invoker<LoadBalanceTest> weightInvoker3;
289+
290+
@Before
291+
public void before() throws Exception {
292+
weightInvoker1 = mock(Invoker.class);
293+
weightInvoker2 = mock(Invoker.class);
294+
weightInvoker3 = mock(Invoker.class);
295+
weightTestInvocation = new RpcInvocation();
296+
weightTestInvocation.setMethodName("test");
297+
URL url1 = URL.valueOf("test1://0:1/DemoService");
298+
url1 = url1.addParameter(Constants.WEIGHT_KEY, 1);
299+
url1 = url1.addParameter(weightTestInvocation.getMethodName() + "." + Constants.WEIGHT_KEY, 1);
300+
url1 = url1.addParameter("active", 0);
301+
URL url2 = URL.valueOf("test2://0:9/DemoService");
302+
url2 = url2.addParameter(Constants.WEIGHT_KEY, 9);
303+
url2 = url2.addParameter(weightTestInvocation.getMethodName() + "." + Constants.WEIGHT_KEY, 9);
304+
url2 = url2.addParameter("active", 0);
305+
URL url3 = URL.valueOf("test3://1:6/DemoService");
306+
url3 = url3.addParameter(Constants.WEIGHT_KEY, 6);
307+
url3 = url3.addParameter(weightTestInvocation.getMethodName() + "." + Constants.WEIGHT_KEY, 6);
308+
url3 = url3.addParameter("active", 1);
309+
given(weightInvoker1.isAvailable()).willReturn(true);
310+
given(weightInvoker1.getUrl()).willReturn(url1);
311+
given(weightInvoker2.isAvailable()).willReturn(true);
312+
given(weightInvoker2.getUrl()).willReturn(url2);
313+
given(weightInvoker3.isAvailable()).willReturn(true);
314+
given(weightInvoker3.getUrl()).willReturn(url3);
315+
weightInvokers.add(weightInvoker1);
316+
weightInvokers.add(weightInvoker2);
317+
weightInvokers.add(weightInvoker3);
318+
weightTestRpcStatus1 = RpcStatus.getStatus(weightInvoker1.getUrl(), weightTestInvocation.getMethodName());
319+
weightTestRpcStatus2 = RpcStatus.getStatus(weightInvoker2.getUrl(), weightTestInvocation.getMethodName());
320+
weightTestRpcStatus3 = RpcStatus.getStatus(weightInvoker3.getUrl(), weightTestInvocation.getMethodName());
321+
// weightTestRpcStatus3 active is 1
322+
RpcStatus.beginCount(weightInvoker3.getUrl(), weightTestInvocation.getMethodName());
323+
}
204324
}

0 commit comments

Comments
 (0)