You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2021/08/23 05:18:02 UTC
[dubbo] branch 3.0 updated: Fix bug of BroadcastClusterInvoker and
add test cases (#8532)
This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.0 by this push:
new d7f2452 Fix bug of BroadcastClusterInvoker and add test cases (#8532)
d7f2452 is described below
commit d7f24524f61a97edd275a838afc1d98d606bf2e3
Author: 灼华 <43...@users.noreply.github.com>
AuthorDate: Mon Aug 23 13:17:43 2021 +0800
Fix bug of BroadcastClusterInvoker and add test cases (#8532)
---
.../cluster/support/BroadcastClusterInvoker.java | 6 +-
.../support/BroadCastClusterInvokerTest.java | 164 +++++++++++++++++++++
2 files changed, 166 insertions(+), 4 deletions(-)
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java
index cf7520f..6b23b3a 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java
@@ -72,20 +72,18 @@ public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
if (null != resultException) {
exception = getRpcException(result.getException());
logger.warn(exception.getMessage(), exception);
+ failIndex++;
if (failIndex == failThresholdIndex) {
break;
- } else {
- failIndex++;
}
}
}
} catch (Throwable e) {
exception = getRpcException(e);
logger.warn(exception.getMessage(), exception);
+ failIndex++;
if (failIndex == failThresholdIndex) {
break;
- } else {
- failIndex++;
}
}
}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/BroadCastClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/BroadCastClusterInvokerTest.java
new file mode 100644
index 0000000..ea09d02
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/BroadCastClusterInvokerTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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.support;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.filter.DemoService;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+
+/**
+ * @see BroadcastClusterInvoker
+ */
+public class BroadCastClusterInvokerTest {
+ private URL url;
+ private Directory<DemoService> dic;
+ private RpcInvocation invocation;
+ private BroadcastClusterInvoker clusterInvoker;
+
+ private MockInvoker invoker1;
+ private MockInvoker invoker2;
+ private MockInvoker invoker3;
+ private MockInvoker invoker4;
+
+
+ @BeforeEach
+ public void setUp() throws Exception {
+
+ dic = mock(Directory.class);
+
+ invoker1 = new MockInvoker();
+ invoker2 = new MockInvoker();
+ invoker3 = new MockInvoker();
+ invoker4 = new MockInvoker();
+
+ url = URL.valueOf("test://127.0.0.1:8080/test");
+ given(dic.getUrl()).willReturn(url);
+ given(dic.getConsumerUrl()).willReturn(url);
+ given(dic.getInterface()).willReturn(DemoService.class);
+
+ invocation = new RpcInvocation();
+ invocation.setMethodName("test");
+
+ clusterInvoker = new BroadcastClusterInvoker(dic);
+ }
+
+
+ @Test
+ public void testNormal() {
+ given(dic.list(invocation)).willReturn(Arrays.asList(invoker1, invoker2, invoker3, invoker4));
+ // Every invoker will be called
+ clusterInvoker.invoke(invocation);
+ assertTrue(invoker1.isInvoked());
+ assertTrue(invoker2.isInvoked());
+ assertTrue(invoker3.isInvoked());
+ assertTrue(invoker4.isInvoked());
+ }
+
+ @Test
+ public void testEx() {
+ given(dic.list(invocation)).willReturn(Arrays.asList(invoker1, invoker2, invoker3, invoker4));
+ invoker1.invokeThrowEx();
+ assertThrows(RpcException.class, () -> {
+ clusterInvoker.invoke(invocation);
+ });
+ // The default failure percentage is 100, even if a certain invoker#invoke throws an exception, other invokers will still be called
+ assertTrue(invoker1.isInvoked());
+ assertTrue(invoker2.isInvoked());
+ assertTrue(invoker3.isInvoked());
+ assertTrue(invoker4.isInvoked());
+ }
+
+ @Test
+ public void testFailPercent() {
+ given(dic.list(invocation)).willReturn(Arrays.asList(invoker1, invoker2, invoker3, invoker4));
+ // We set the failure percentage to 75, which means that when the number of call failures is 4*(75/100) = 3,
+ // an exception will be thrown directly and subsequent invokers will not be called.
+ url = url.addParameter("broadcast.fail.percent", 75);
+ given(dic.getConsumerUrl()).willReturn(url);
+ invoker1.invokeThrowEx();
+ invoker2.invokeThrowEx();
+ invoker3.invokeThrowEx();
+ invoker4.invokeThrowEx();
+ assertThrows(RpcException.class, () -> {
+ clusterInvoker.invoke(invocation);
+ });
+ assertTrue(invoker1.isInvoked());
+ assertTrue(invoker2.isInvoked());
+ assertTrue(invoker3.isInvoked());
+ assertFalse(invoker4.isInvoked());
+ }
+}
+
+class MockInvoker implements Invoker<DemoService> {
+ private static int count = 0;
+ private URL url = URL.valueOf("test://127.0.0.1:8080/test");
+ private boolean throwEx = false;
+ private boolean invoked = false;
+
+ @Override
+ public URL getUrl() {
+ return url;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return false;
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+
+ @Override
+ public Class<DemoService> getInterface() {
+ return DemoService.class;
+ }
+
+ @Override
+ public Result invoke(Invocation invocation) throws RpcException {
+ invoked = true;
+ if (throwEx) {
+ throwEx = false;
+ throw new RpcException();
+ }
+ return null;
+ }
+
+ public void invokeThrowEx() {
+ throwEx = true;
+ }
+
+ public boolean isInvoked() {
+ return invoked;
+ }
+}