This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
The following commit(s) were added to refs/heads/master by this push:
new aab6a1d39 [SCB-2841]zone-aware filter support configure group size
ratio (#4107)
aab6a1d39 is described below
commit aab6a1d393927693aa69b81bcab4562383f67004
Author: liubao68 <[email protected]>
AuthorDate: Fri Dec 8 15:12:00 2023 +0800
[SCB-2841]zone-aware filter support configure group size ratio (#4107)
---
.../filter/ZoneAwareDiscoveryFilter.java | 28 +++++-
.../loadbalance/TestLoadBalanceFilter2.java | 16 +--
.../filter/TestZoneAwareDiscoveryFilter.java | 111 +++++++++++++++++++++
3 files changed, 140 insertions(+), 15 deletions(-)
diff --git
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/ZoneAwareDiscoveryFilter.java
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/ZoneAwareDiscoveryFilter.java
index 62eee1b3b..eb86fc8d5 100644
---
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/ZoneAwareDiscoveryFilter.java
+++
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/ZoneAwareDiscoveryFilter.java
@@ -34,6 +34,10 @@ public class ZoneAwareDiscoveryFilter extends
AbstractGroupDiscoveryFilter {
public static final String GROUP_SIZE = "zone_aware_group_size";
+ public static final String CONFIG_ENABLED =
"servicecomb.loadbalance.filter.zoneaware.enabled";
+
+ public static final String CONFIG_RATIO =
"servicecomb.loadbalance.filter.zoneaware.ratio";
+
private DataCenterProperties dataCenterProperties;
@Autowired
@@ -49,10 +53,15 @@ public class ZoneAwareDiscoveryFilter extends
AbstractGroupDiscoveryFilter {
@Override
public boolean enabled() {
- return
environment.getProperty("servicecomb.loadbalance.filter.zoneaware.enabled",
+ return environment.getProperty(CONFIG_ENABLED,
Boolean.class, true);
}
+ private int getRatio() {
+ return environment.getProperty(CONFIG_RATIO,
+ int.class, 50);
+ }
+
@Override
protected String contextParameter() {
return PARAMETER;
@@ -87,16 +96,22 @@ public class ZoneAwareDiscoveryFilter extends
AbstractGroupDiscoveryFilter {
}
}
- if (!instancesRegionAndAZMatch.isEmpty()) {
+ int ratio = getRatio();
+
+ if (hasEnoughMembers(instances.size(), instancesRegionAndAZMatch.size(),
ratio)) {
parent.child(GROUP_PREFIX + groups, new DiscoveryTreeNode()
.subName(parent, GROUP_PREFIX +
groups).data(instancesRegionAndAZMatch));
groups++;
+ } else {
+ instancesAZMatch.addAll(instancesRegionAndAZMatch);
}
- if (!instancesAZMatch.isEmpty()) {
+ if (hasEnoughMembers(instances.size(), instancesAZMatch.size(), ratio)) {
parent.child(GROUP_PREFIX + groups, new DiscoveryTreeNode()
.subName(parent, GROUP_PREFIX + groups).data(instancesAZMatch));
groups++;
+ } else {
+ instancesNoMatch.addAll(instancesAZMatch);
}
parent.child(GROUP_PREFIX + groups, new DiscoveryTreeNode()
@@ -105,6 +120,13 @@ public class ZoneAwareDiscoveryFilter extends
AbstractGroupDiscoveryFilter {
parent.attribute(GROUP_SIZE, groups);
}
+ private boolean hasEnoughMembers(int totalSize, int groupSize, int ratio) {
+ if (totalSize == 0 || groupSize == 0) {
+ return false;
+ }
+ return Math.floorDiv(groupSize * 100, totalSize) >= ratio;
+ }
+
private boolean regionAndAZMatch(StatefulDiscoveryInstance target) {
if (dataCenterProperties.getRegion() != null
&& dataCenterProperties.getAvailableZone() != null &&
target.getDataCenterInfo() != null) {
diff --git
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceFilter2.java
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceFilter2.java
index 5e4c47e9c..e2b4418bc 100644
---
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceFilter2.java
+++
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceFilter2.java
@@ -57,6 +57,10 @@ public class TestLoadBalanceFilter2 {
public void setUp() {
Mockito.when(environment.getProperty("servicecomb.loadbalance.userDefinedEndpoint.enabled",
boolean.class, false)).thenReturn(false);
+
Mockito.when(environment.getProperty("servicecomb.loadbalance.filter.zoneaware.enabled",
+ Boolean.class, true)).thenReturn(true);
+
Mockito.when(environment.getProperty("servicecomb.loadbalance.filter.zoneaware.ratio",
+ int.class, 50)).thenReturn(0);
}
@Test
@@ -137,8 +141,6 @@ public class TestLoadBalanceFilter2 {
zoneAwareDiscoveryFilter.setDataCenterProperties(myself);
ServerDiscoveryFilter serverDiscoveryFilter = new ServerDiscoveryFilter();
serverDiscoveryFilter.setScbEngine(scbEngine);
-
Mockito.when(environment.getProperty("servicecomb.loadbalance.filter.zoneaware.enabled",
- Boolean.class, true)).thenReturn(true);
discoveryTree.setDiscoveryFilters(Arrays.asList(zoneAwareDiscoveryFilter,
serverDiscoveryFilter));
handler = new LoadBalanceFilter(new ExtensionsManager(new ArrayList<>()),
@@ -222,8 +224,6 @@ public class TestLoadBalanceFilter2 {
ZoneAwareDiscoveryFilter zoneAwareDiscoveryFilter = new
ZoneAwareDiscoveryFilter();
zoneAwareDiscoveryFilter.setEnvironment(environment);
zoneAwareDiscoveryFilter.setDataCenterProperties(myself);
-
Mockito.when(environment.getProperty("servicecomb.loadbalance.filter.zoneaware.enabled",
- Boolean.class, true)).thenReturn(true);
ServerDiscoveryFilter serverDiscoveryFilter = new ServerDiscoveryFilter();
serverDiscoveryFilter.setScbEngine(scbEngine);
discoveryTree.setDiscoveryFilters(Arrays.asList(zoneAwareDiscoveryFilter,
@@ -318,8 +318,6 @@ public class TestLoadBalanceFilter2 {
ZoneAwareDiscoveryFilter zoneAwareDiscoveryFilter = new
ZoneAwareDiscoveryFilter();
zoneAwareDiscoveryFilter.setEnvironment(environment);
zoneAwareDiscoveryFilter.setDataCenterProperties(myself);
-
Mockito.when(environment.getProperty("servicecomb.loadbalance.filter.zoneaware.enabled",
- Boolean.class, true)).thenReturn(true);
ServerDiscoveryFilter serverDiscoveryFilter = new ServerDiscoveryFilter();
serverDiscoveryFilter.setScbEngine(scbEngine);
discoveryTree.setDiscoveryFilters(Arrays.asList(zoneAwareDiscoveryFilter,
@@ -416,11 +414,8 @@ public class TestLoadBalanceFilter2 {
.thenReturn(parent);
DiscoveryTree discoveryTree = new DiscoveryTree(discoveryManager);
ZoneAwareDiscoveryFilter zoneAwareDiscoveryFilter = new
ZoneAwareDiscoveryFilter();
- Environment environment = Mockito.mock(Environment.class);
zoneAwareDiscoveryFilter.setEnvironment(environment);
zoneAwareDiscoveryFilter.setDataCenterProperties(myself);
-
Mockito.when(environment.getProperty("servicecomb.loadbalance.filter.zoneaware.enabled",
- Boolean.class, true)).thenReturn(true);
ServerDiscoveryFilter serverDiscoveryFilter = new ServerDiscoveryFilter();
serverDiscoveryFilter.setScbEngine(scbEngine);
discoveryTree.setDiscoveryFilters(Arrays.asList(zoneAwareDiscoveryFilter,
@@ -516,11 +511,8 @@ public class TestLoadBalanceFilter2 {
.thenReturn(parent);
DiscoveryTree discoveryTree = new DiscoveryTree(discoveryManager);
ZoneAwareDiscoveryFilter zoneAwareDiscoveryFilter = new
ZoneAwareDiscoveryFilter();
- Environment environment = Mockito.mock(Environment.class);
zoneAwareDiscoveryFilter.setEnvironment(environment);
zoneAwareDiscoveryFilter.setDataCenterProperties(myself);
-
Mockito.when(environment.getProperty("servicecomb.loadbalance.filter.zoneaware.enabled",
- Boolean.class, true)).thenReturn(true);
ServerDiscoveryFilter serverDiscoveryFilter = new ServerDiscoveryFilter();
serverDiscoveryFilter.setScbEngine(scbEngine);
discoveryTree.setDiscoveryFilters(Arrays.asList(zoneAwareDiscoveryFilter,
diff --git
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestZoneAwareDiscoveryFilter.java
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestZoneAwareDiscoveryFilter.java
new file mode 100644
index 000000000..dfab80adc
--- /dev/null
+++
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestZoneAwareDiscoveryFilter.java
@@ -0,0 +1,111 @@
+/*
+ * 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.servicecomb.loadbalance.filter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.servicecomb.config.DataCenterProperties;
+import org.apache.servicecomb.registry.api.DataCenterInfo;
+import org.apache.servicecomb.registry.api.DiscoveryInstance;
+import org.apache.servicecomb.registry.discovery.DiscoveryContext;
+import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode;
+import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.springframework.core.env.Environment;
+
+public class TestZoneAwareDiscoveryFilter {
+ Environment environment = Mockito.mock(Environment.class);
+
+ @BeforeEach
+ public void setUp() {
+
Mockito.when(environment.getProperty("servicecomb.loadbalance.filter.zoneaware.enabled",
+ Boolean.class, true)).thenReturn(true);
+ }
+
+ @Test
+ public void test_not_enough_instance() {
+
Mockito.when(environment.getProperty("servicecomb.loadbalance.filter.zoneaware.ratio",
+ int.class, 50)).thenReturn(50);
+
+ ZoneAwareDiscoveryFilter filter = new ZoneAwareDiscoveryFilter();
+ filter.setEnvironment(environment);
+
+ // set up data
+ DataCenterProperties myself = new DataCenterProperties();
+ myself.setName("test");
+ myself.setRegion("test-Region");
+ myself.setAvailableZone("test-zone");
+ filter.setDataCenterProperties(myself);
+
+ DiscoveryInstance discoveryInstance =
Mockito.mock(DiscoveryInstance.class);
+ StatefulDiscoveryInstance allmatchInstance = new
StatefulDiscoveryInstance(discoveryInstance);
+ DataCenterInfo info = new DataCenterInfo();
+ info.setName("test");
+ info.setRegion("test-Region");
+ info.setAvailableZone("test-zone");
+ List<String> allMatchEndpoint = new ArrayList<>();
+ allMatchEndpoint.add("rest://localhost:9090");
+
Mockito.when(discoveryInstance.getEndpoints()).thenReturn(allMatchEndpoint);
+ Mockito.when(discoveryInstance.getDataCenterInfo()).thenReturn(info);
+
Mockito.when(discoveryInstance.getInstanceId()).thenReturn("allmatchInstance");
+
+ DiscoveryInstance regionMatchDiscoveryInstance =
Mockito.mock(DiscoveryInstance.class);
+ StatefulDiscoveryInstance regionMatchInstance = new
StatefulDiscoveryInstance(regionMatchDiscoveryInstance);
+ DataCenterInfo regionMatchInfo = new DataCenterInfo();
+ regionMatchInfo.setName("test");
+ regionMatchInfo.setRegion("test-Region");
+ regionMatchInfo.setAvailableZone("test-zone2");
+ List<String> regionMatchEndpoint = new ArrayList<>();
+ regionMatchEndpoint.add("rest://localhost:9091");
+
Mockito.when(regionMatchDiscoveryInstance.getEndpoints()).thenReturn(regionMatchEndpoint);
+
Mockito.when(regionMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(regionMatchInfo);
+
Mockito.when(regionMatchDiscoveryInstance.getInstanceId()).thenReturn("regionMatchInstance");
+
+ DiscoveryInstance noneMatchDiscoveryInstance =
Mockito.mock(DiscoveryInstance.class);
+ StatefulDiscoveryInstance noneMatchInstance = new
StatefulDiscoveryInstance(noneMatchDiscoveryInstance);
+ DataCenterInfo noneMatchInfo = new DataCenterInfo();
+ noneMatchInfo.setName("test");
+ noneMatchInfo.setRegion("test-Region2");
+ noneMatchInfo.setAvailableZone("test-zone2");
+ List<String> noMatchEndpoint = new ArrayList<>();
+ noMatchEndpoint.add("rest://localhost:9092");
+
Mockito.when(noneMatchDiscoveryInstance.getEndpoints()).thenReturn(noMatchEndpoint);
+
Mockito.when(noneMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(noneMatchInfo);
+
Mockito.when(noneMatchDiscoveryInstance.getInstanceId()).thenReturn("noneMatchInstance");
+
+ // run test
+ List<StatefulDiscoveryInstance> data = Arrays.asList(allmatchInstance,
regionMatchInstance, noneMatchInstance);
+ DiscoveryTreeNode parent = new
DiscoveryTreeNode().name("parent").data(data);
+ DiscoveryContext context = new DiscoveryContext();
+ DiscoveryTreeNode result = filter.discovery(context, parent);
+
+ // check result
+ Integer level = context.getContextParameter(filter.contextParameter());
+ Integer groups = parent.attribute(filter.groupsSizeParameter());
+ List<StatefulDiscoveryInstance> resultData = result.data();
+ Assertions.assertEquals(1, level);
+ Assertions.assertEquals(2, groups);
+ Assertions.assertEquals(2, resultData.size());
+ Assertions.assertEquals("regionMatchInstance",
resultData.get(0).getInstanceId());
+ Assertions.assertEquals("allmatchInstance",
resultData.get(1).getInstanceId());
+ }
+}