[SCB-2645] Fix route rule will throw NPE when version is empty (#3228)
diff --git a/governance/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java b/governance/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java
index 500812b..d3f8f76 100644
--- a/governance/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java
+++ b/governance/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java
@@ -116,6 +116,9 @@
TagItem targetTag = null;
int maxMatch = 0;
for (RouteItem entry : invokeRule.getRoute()) {
+ if (entry.getTagitem() == null){
+ continue;
+ }
int nowMatch = entry.getTagitem().matchNum(tagItem);
if (nowMatch > maxMatch) {
maxMatch = nowMatch;
diff --git a/governance/src/main/java/org/apache/servicecomb/router/model/RouteItem.java b/governance/src/main/java/org/apache/servicecomb/router/model/RouteItem.java
index e48d4ee..f2017a9 100644
--- a/governance/src/main/java/org/apache/servicecomb/router/model/RouteItem.java
+++ b/governance/src/main/java/org/apache/servicecomb/router/model/RouteItem.java
@@ -36,7 +36,7 @@
public void initTagItem() {
- if (tags != null && tags.containsKey("version")) {
+ if (tags != null) {
tagitem = new TagItem(tags);
}
}
diff --git a/governance/src/test/java/org/apache/servicecomb/router/distribute/DistributeTest.java b/governance/src/test/java/org/apache/servicecomb/router/distribute/DistributeTest.java
new file mode 100644
index 0000000..e26e4f0
--- /dev/null
+++ b/governance/src/test/java/org/apache/servicecomb/router/distribute/DistributeTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.router.distribute;
+
+import org.apache.servicecomb.router.RouterFilter;
+import org.apache.servicecomb.router.ServiceIns;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigDataApplicationContextInitializer.class)
+public class DistributeTest {
+ private static final String TARGET_SERVICE_NAME = "test_server1";
+
+ private RouterFilter routerFilter;
+
+ private RouterDistributor<ServiceIns, ServiceIns> routerDistributor;
+
+ @Autowired
+ public void setRouterFilter(RouterFilter routerFilter) {
+ this.routerFilter = routerFilter;
+ }
+
+ @Autowired
+ public void setRouterDistributor(RouterDistributor<ServiceIns, ServiceIns> routerDistributor) {
+ this.routerDistributor = routerDistributor;
+ }
+
+ @Test
+ public void testDistribute() {
+ List<ServiceIns> list = initServiceList();
+ HashMap<String, String> header = new HashMap<>();
+ List<ServiceIns> listOfServers = routerFilter
+ .getFilteredListOfServers(list, TARGET_SERVICE_NAME, header, routerDistributor);
+ Assertions.assertNotNull(listOfServers);
+ for (ServiceIns server : listOfServers) {
+ Assertions.assertEquals(TARGET_SERVICE_NAME, server.getServerName());
+ }
+ int serverNum1 = 0;
+ int serverNum2 = 0;
+
+ for (int i = 0; i < 10; i++) {
+ List<ServiceIns> serverList = routerFilter
+ .getFilteredListOfServers(list, TARGET_SERVICE_NAME, header, routerDistributor);
+ for (ServiceIns serviceIns : serverList) {
+ if ("01".equals(serviceIns.getId())) {
+ serverNum1++;
+ } else if ("02".equals(serviceIns.getId())) {
+ serverNum2++;
+ }
+ }
+ }
+ boolean flag = false;
+ if (Math.round(serverNum2 * 1.0 / serverNum1) == 4) {
+ flag = true;
+ }
+ Assertions.assertTrue(flag);
+ }
+
+ List<ServiceIns> initServiceList() {
+ ServiceIns serviceIns1 = new ServiceIns("01", "test_server1");
+ ServiceIns serviceIns2 = new ServiceIns("02", "test_server1");
+ serviceIns1.setVersion("1.0");
+ serviceIns2.setVersion("2.0");
+ serviceIns1.addTags("x-group", "red");
+ serviceIns2.addTags("x-group", "green");
+ List<ServiceIns> list = new ArrayList<>();
+ list.add(serviceIns1);
+ list.add(serviceIns2);
+ return list;
+ }
+}
diff --git a/governance/src/test/resources/application.yaml b/governance/src/test/resources/application.yaml
index d4cf757..e5c0842 100644
--- a/governance/src/test/resources/application.yaml
+++ b/governance/src/test/resources/application.yaml
@@ -144,3 +144,31 @@
wrongIngored: |
delayTime: -1
type: ERROR
+
+ routeRule:
+ test_server1: | # 服务名
+ - precedence: 1 # 优先级,数字越大,优先级越高。
+ match: # 请求匹配规则。0..N个,不配置表示匹配。
+ headers: # header 匹配
+ region: # 如果配置了多个 header,那么所有的 header 规则都必须和请求匹配
+ exact: 'providerRegion'
+ caseInsensitive: false # 不区分大小写
+ type:
+ regex: gray_[a-z]+ # java 正则表达式匹配
+ caseInsensitive: true # 区分大小写
+ route: # 路由规则
+ - weight: 20 # 权重值
+ tags:
+ version: 1.0.0 # 实例标记。满足标记条件的实例放到这一组。
+ - weight: 80 # 权重值
+ tags:
+ version: 2.0.0 # 实例标记。满足标记条件的实例放到这一组。
+
+ - precedence: 2
+ route:
+ - weight: 20
+ tags:
+ x-group: red
+ - weight: 80
+ tags:
+ x-group: green