blob: c96c0fc391a82eb6a6ba97c48e3420b44ad25849 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.loadbalance;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.utils.JsonUtils;
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.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_WARMUP;
import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_WEIGHT;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* RoundRobinLoadBalanceTest
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class LoadBalanceBaseTest {
Invocation invocation;
List<Invoker<LoadBalanceBaseTest>> invokers = new ArrayList<Invoker<LoadBalanceBaseTest>>();
Invoker<LoadBalanceBaseTest> invoker1;
Invoker<LoadBalanceBaseTest> invoker2;
Invoker<LoadBalanceBaseTest> invoker3;
Invoker<LoadBalanceBaseTest> invoker4;
Invoker<LoadBalanceBaseTest> invoker5;
RpcStatus weightTestRpcStatus1;
RpcStatus weightTestRpcStatus2;
RpcStatus weightTestRpcStatus3;
RpcStatus weightTestRpcStatus5;
RpcInvocation weightTestInvocation;
/**
* @throws java.lang.Exception
*/
@BeforeAll
public static void setUpBeforeClass() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@BeforeEach
public void setUp() throws Exception {
invocation = mock(Invocation.class);
given(invocation.getMethodName()).willReturn("method1");
given(invocation.getArguments()).willReturn(new Object[] {"arg1","arg2","arg3"});
invoker1 = mock(Invoker.class);
invoker2 = mock(Invoker.class);
invoker3 = mock(Invoker.class);
invoker4 = mock(Invoker.class);
invoker5 = mock(Invoker.class);
URL url1 = URL.valueOf("test://127.0.0.1:1/DemoService");
URL url2 = URL.valueOf("test://127.0.0.1:2/DemoService");
URL url3 = URL.valueOf("test://127.0.0.1:3/DemoService");
URL url4 = URL.valueOf("test://127.0.0.1:4/DemoService");
URL url5 = URL.valueOf("test://127.0.0.1:5/DemoService");
given(invoker1.isAvailable()).willReturn(true);
given(invoker1.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(invoker1.getUrl()).willReturn(url1);
given(invoker2.isAvailable()).willReturn(true);
given(invoker2.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(invoker2.getUrl()).willReturn(url2);
given(invoker3.isAvailable()).willReturn(true);
given(invoker3.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(invoker3.getUrl()).willReturn(url3);
given(invoker4.isAvailable()).willReturn(true);
given(invoker4.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(invoker4.getUrl()).willReturn(url4);
given(invoker5.isAvailable()).willReturn(true);
given(invoker5.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(invoker5.getUrl()).willReturn(url5);
invokers.add(invoker1);
invokers.add(invoker2);
invokers.add(invoker3);
invokers.add(invoker4);
invokers.add(invoker5);
}
public Map<Invoker, AtomicLong> getInvokeCounter(int runs, String loadbalanceName) {
Map<Invoker, AtomicLong> counter = new ConcurrentHashMap<Invoker, AtomicLong>();
LoadBalance lb = getLoadBalance(loadbalanceName);
for (Invoker invoker : invokers) {
counter.put(invoker, new AtomicLong(0));
}
URL url = invokers.get(0).getUrl();
for (int i = 0; i < runs; i++) {
Invoker sinvoker = lb.select(invokers, url, invocation);
counter.get(sinvoker).incrementAndGet();
}
return counter;
}
protected AbstractLoadBalance getLoadBalance(String loadbalanceName) {
return (AbstractLoadBalance) ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(loadbalanceName);
}
@Test
public void testLoadBalanceWarmup() {
Assertions.assertEquals(1, calculateDefaultWarmupWeight(0));
Assertions.assertEquals(1, calculateDefaultWarmupWeight(13));
Assertions.assertEquals(1, calculateDefaultWarmupWeight(6 * 1000));
Assertions.assertEquals(2, calculateDefaultWarmupWeight(12 * 1000));
Assertions.assertEquals(10, calculateDefaultWarmupWeight(60 * 1000));
Assertions.assertEquals(50, calculateDefaultWarmupWeight(5 * 60 * 1000));
Assertions.assertEquals(50, calculateDefaultWarmupWeight(5 * 60 * 1000 + 23));
Assertions.assertEquals(50, calculateDefaultWarmupWeight(5 * 60 * 1000 + 5999));
Assertions.assertEquals(51, calculateDefaultWarmupWeight(5 * 60 * 1000 + 6000));
Assertions.assertEquals(90, calculateDefaultWarmupWeight(9 * 60 * 1000));
Assertions.assertEquals(98, calculateDefaultWarmupWeight(10 * 60 * 1000 - 12 * 1000));
Assertions.assertEquals(99, calculateDefaultWarmupWeight(10 * 60 * 1000 - 6 * 1000));
Assertions.assertEquals(100, calculateDefaultWarmupWeight(10 * 60 * 1000));
Assertions.assertEquals(100, calculateDefaultWarmupWeight(20 * 60 * 1000));
}
/**
* handle default data
*
* @return
*/
private static int calculateDefaultWarmupWeight(int uptime) {
return AbstractLoadBalance.calculateWarmupWeight(uptime, DEFAULT_WARMUP, DEFAULT_WEIGHT);
}
/*------------------------------------test invokers for weight---------------------------------------*/
protected static class InvokeResult {
private AtomicLong count = new AtomicLong();
private int weight = 0;
private int totalWeight = 0;
public InvokeResult(int weight) {
this.weight = weight;
}
public AtomicLong getCount() {
return count;
}
public int getWeight() {
return weight;
}
public int getTotalWeight() {
return totalWeight;
}
public void setTotalWeight(int totalWeight) {
this.totalWeight = totalWeight;
}
public int getExpected(int runCount) {
return getWeight() * runCount / getTotalWeight();
}
public float getDeltaPercentage(int runCount) {
int expected = getExpected(runCount);
return Math.abs((expected - getCount().get()) * 100.0f / expected);
}
@Override
public String toString() {
return JsonUtils.getJson().toJson(this);
}
}
protected List<Invoker<LoadBalanceBaseTest>> weightInvokers = new ArrayList<Invoker<LoadBalanceBaseTest>>();
protected List<Invoker<LoadBalanceBaseTest>> weightInvokersSR= new ArrayList<Invoker<LoadBalanceBaseTest>>();
protected Invoker<LoadBalanceBaseTest> weightInvoker1;
protected Invoker<LoadBalanceBaseTest> weightInvoker2;
protected Invoker<LoadBalanceBaseTest> weightInvoker3;
protected Invoker<LoadBalanceBaseTest> weightInvokerTmp;
protected Invoker<LoadBalanceBaseTest> weightInvoker5;
@BeforeEach
public void before() throws Exception {
weightInvoker1 = mock(Invoker.class, Mockito.withSettings().stubOnly());
weightInvoker2 = mock(Invoker.class, Mockito.withSettings().stubOnly());
weightInvoker3 = mock(Invoker.class, Mockito.withSettings().stubOnly());
weightInvokerTmp = mock(Invoker.class, Mockito.withSettings().stubOnly());
weightInvoker5 = mock(Invoker.class, Mockito.withSettings().stubOnly());
weightTestInvocation = new RpcInvocation();
weightTestInvocation.setMethodName("test");
URL url1 = URL.valueOf("test1://127.0.0.1:11/DemoService?weight=1&active=0");
URL url2 = URL.valueOf("test2://127.0.0.1:12/DemoService?weight=9&active=0");
URL url3 = URL.valueOf("test3://127.0.0.1:13/DemoService?weight=6&active=1");
URL urlTmp = URL.valueOf("test4://127.0.0.1:9999/DemoService?weight=11&active=0");
URL url5 = URL.valueOf("test5://127.0.0.1:15/DemoService?weight=15&active=0");
given(weightInvoker1.isAvailable()).willReturn(true);
given(weightInvoker1.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(weightInvoker1.getUrl()).willReturn(url1);
given(weightInvoker2.isAvailable()).willReturn(true);
given(weightInvoker2.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(weightInvoker2.getUrl()).willReturn(url2);
given(weightInvoker3.isAvailable()).willReturn(true);
given(weightInvoker3.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(weightInvoker3.getUrl()).willReturn(url3);
given(weightInvokerTmp.isAvailable()).willReturn(true);
given(weightInvokerTmp.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(weightInvokerTmp.getUrl()).willReturn(urlTmp);
given(weightInvoker5.isAvailable()).willReturn(true);
given(weightInvoker5.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(weightInvoker5.getUrl()).willReturn(url5);
weightInvokers.add(weightInvoker1);
weightInvokers.add(weightInvoker2);
weightInvokers.add(weightInvoker3);
weightInvokersSR.add(weightInvoker1);
weightInvokersSR.add(weightInvoker2);
weightInvokersSR.add(weightInvoker5);
weightTestRpcStatus1 = RpcStatus.getStatus(weightInvoker1.getUrl(), weightTestInvocation.getMethodName());
weightTestRpcStatus2 = RpcStatus.getStatus(weightInvoker2.getUrl(), weightTestInvocation.getMethodName());
weightTestRpcStatus3 = RpcStatus.getStatus(weightInvoker3.getUrl(), weightTestInvocation.getMethodName());
weightTestRpcStatus5 = RpcStatus.getStatus(weightInvoker5.getUrl(), weightTestInvocation.getMethodName());
// weightTestRpcStatus3 active is 1
RpcStatus.beginCount(weightInvoker3.getUrl(), weightTestInvocation.getMethodName());
// weightTestRpcStatus5 shortest response time of success calls is bigger than 0
// weightTestRpcStatus5 active is 1
RpcStatus.beginCount(weightInvoker5.getUrl(), weightTestInvocation.getMethodName());
RpcStatus.endCount(weightInvoker5.getUrl(), weightTestInvocation.getMethodName(), 5000L, true);
RpcStatus.beginCount(weightInvoker5.getUrl(), weightTestInvocation.getMethodName());
}
protected Map<Invoker, InvokeResult> getWeightedInvokeResult(int runs, String loadbalanceName) {
Map<Invoker, InvokeResult> counter = new ConcurrentHashMap<Invoker, InvokeResult>();
AbstractLoadBalance lb = getLoadBalance(loadbalanceName);
int totalWeight = 0;
for (int i = 0; i < weightInvokers.size(); i ++) {
InvokeResult invokeResult = new InvokeResult(lb.getWeight(weightInvokers.get(i), weightTestInvocation));
counter.put(weightInvokers.get(i), invokeResult);
totalWeight += invokeResult.getWeight();
}
for (InvokeResult invokeResult : counter.values()) {
invokeResult.setTotalWeight(totalWeight);
}
URL url = weightInvokers.get(0).getUrl();
for (int i = 0; i < runs; i++) {
Invoker sinvoker = lb.select(weightInvokers, url, weightTestInvocation);
counter.get(sinvoker).getCount().incrementAndGet();
}
return counter;
}
}