This is an automated email from the ASF dual-hosted git repository.

albumenj pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.1 by this push:
     new a204f61839 Support consistent hash load balance when gerenic invoke 
(#10799)
a204f61839 is described below

commit a204f6183989f9b96bedc2a7a41b76470938fa7f
Author: nobodyw-cell <[email protected]>
AuthorDate: Sun Nov 6 17:13:52 2022 +0800

    Support consistent hash load balance when gerenic invoke (#10799)
---
 .../loadbalance/ConsistentHashLoadBalance.java     | 11 +++++++--
 .../loadbalance/ConsistentHashLoadBalanceTest.java | 28 ++++++++++++++++++++++
 .../cluster/loadbalance/LoadBalanceBaseTest.java   | 23 ++++++++++++++++++
 3 files changed, 60 insertions(+), 2 deletions(-)

diff --git 
a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
 
b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
index 15c7066e06..8604def436 100644
--- 
a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
+++ 
b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
@@ -28,6 +28,7 @@ import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
 import static 
org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
 
 /**
@@ -96,15 +97,21 @@ public class ConsistentHashLoadBalance extends 
AbstractLoadBalance {
         }
 
         public Invoker<T> select(Invocation invocation) {
-            String key = toKey(invocation.getArguments());
+            boolean isGeneric = invocation.getMethodName().equals($INVOKE);
+            String key = toKey(invocation.getArguments(),isGeneric);
+
             byte[] digest = Bytes.getMD5(key);
             return selectForKey(hash(digest, 0));
         }
 
+        private String toKey(Object[] args, boolean isGeneric) {
+            return isGeneric ? toKey((Object[]) args[1]) : toKey(args);
+        }
+
         private String toKey(Object[] args) {
             StringBuilder buf = new StringBuilder();
             for (int i : argumentIndex) {
-                if (i >= 0 && i < args.length) {
+                if (i >= 0 && args != null && i < args.length) {
                     buf.append(args[i]);
                 }
             }
diff --git 
a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalanceTest.java
 
b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalanceTest.java
index d9b78afd69..6d1381c993 100644
--- 
a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalanceTest.java
+++ 
b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalanceTest.java
@@ -33,6 +33,34 @@ import java.util.concurrent.atomic.AtomicLong;
 @SuppressWarnings("rawtypes")
 public class ConsistentHashLoadBalanceTest extends LoadBalanceBaseTest {
 
+    @Test
+    public void testConsistentHashLoadBalanceInGenericCall() {
+        int runs = 10000;
+        Map<Invoker, AtomicLong> genericInvokeCounter = 
getGenericInvokeCounter(runs, ConsistentHashLoadBalance.NAME);
+        Map<Invoker, AtomicLong> invokeCounter = getInvokeCounter(runs, 
ConsistentHashLoadBalance.NAME);
+
+        Invoker genericHitted = findHitted(genericInvokeCounter);
+        Invoker hitted = findHitted(invokeCounter);
+
+        Assertions.assertEquals(hitted,
+            genericHitted, "hitted should equals to genericHitted");
+    }
+
+    private Invoker findHitted(Map<Invoker,AtomicLong> invokerCounter) {
+        Invoker invoker = null;
+
+        for (Map.Entry<Invoker,AtomicLong> entry : invokerCounter.entrySet()) {
+            if (entry.getValue().longValue() > 0) {
+                invoker = entry.getKey();
+                break;
+            }
+        }
+
+        Assertions.assertNotNull(invoker,"invoker should be found");
+
+        return null;
+    }
+
     @Test
     public void testConsistentHashLoadBalance() {
         int runs = 10000;
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 c96c0fc391..cab69a1302 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
@@ -48,6 +48,7 @@ import static org.mockito.Mockito.mock;
 @SuppressWarnings({"unchecked", "rawtypes"})
 public class LoadBalanceBaseTest {
     Invocation invocation;
+    Invocation genericInvocation;
     List<Invoker<LoadBalanceBaseTest>> invokers = new 
ArrayList<Invoker<LoadBalanceBaseTest>>();
     Invoker<LoadBalanceBaseTest> invoker1;
     Invoker<LoadBalanceBaseTest> invoker2;
@@ -79,6 +80,14 @@ public class LoadBalanceBaseTest {
         given(invocation.getMethodName()).willReturn("method1");
         given(invocation.getArguments()).willReturn(new Object[] 
{"arg1","arg2","arg3"});
 
+        genericInvocation = mock(Invocation.class);
+        String methodName = "method1";
+        given(genericInvocation.getMethodName()).willReturn("$invoke");
+        String[] paraTypes = new String[] 
{String.class.getName(),String.class.getName(),String.class.getName()};
+        Object[] argsObject = new Object[] {"arg1","arg2","arg3"};
+        Object[] args = new Object[] {methodName,paraTypes,argsObject};
+        given(genericInvocation.getArguments()).willReturn(args);
+
         invoker1 = mock(Invoker.class);
         invoker2 = mock(Invoker.class);
         invoker3 = mock(Invoker.class);
@@ -132,6 +141,20 @@ public class LoadBalanceBaseTest {
         return counter;
     }
 
+    public Map<Invoker, AtomicLong> getGenericInvokeCounter(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, genericInvocation);
+            counter.get(sinvoker).incrementAndGet();
+        }
+        return counter;
+    }
+
     protected AbstractLoadBalance getLoadBalance(String loadbalanceName) {
         return (AbstractLoadBalance) 
ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(loadbalanceName);
     }

Reply via email to