You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2021/03/16 11:51:45 UTC
[dubbo] branch 3.0-preview updated: Brand new routing rule (#7372)
This is an automated email from the ASF dual-hosted git repository.
liujun pushed a commit to branch 3.0-preview
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.0-preview by this push:
new 7c505f7 Brand new routing rule (#7372)
7c505f7 is described below
commit 7c505f7467a7bbd6ef0daccac6f436673e6ad665
Author: qinliujie <li...@alibaba-inc.com>
AuthorDate: Tue Mar 16 19:51:23 2021 +0800
Brand new routing rule (#7372)
---
dubbo-cluster/pom.xml | 4 +-
.../org/apache/dubbo/registry/AddressListener.java | 0
.../router/mesh/route/MeshAppRuleListener.java | 98 ++
.../route/MeshRuleAddressListenerInterceptor.java | 51 +
.../cluster/router/mesh/route/MeshRuleManager.java | 79 ++
.../cluster/router/mesh/route/MeshRuleRouter.java | 359 +++++
.../router/mesh/route/MeshRuleRouterFactory.java | 29 +-
.../rpc/cluster/router/mesh/rule/BaseRule.java | 60 +
.../router/mesh/rule/VsDestinationGroup.java | 55 +
.../rule/destination/ConnectionPoolSettings.java | 21 +-
.../mesh/rule/destination/DestinationRule.java | 36 +-
.../mesh/rule/destination/DestinationRuleSpec.java | 60 +
.../router/mesh/rule/destination/Subset.java | 45 +-
.../router/mesh/rule/destination/TCPSettings.java | 24 +-
.../router/mesh/rule/destination/TcpKeepalive.java | 23 +-
.../mesh/rule/destination/TrafficPolicy.java | 35 +-
.../destination/loadbalance/ConsistentHashLB.java | 21 +-
.../loadbalance/LoadBalancerSettings.java | 43 +-
.../rule/destination/loadbalance/SimpleLB.java | 25 +-
.../rule/virtualservice/DubboMatchRequest.java | 130 ++
.../mesh/rule/virtualservice/DubboRoute.java | 62 +
.../mesh/rule/virtualservice/DubboRouteDetail.java | 62 +
.../rule/virtualservice/VirtualServiceRule.java | 36 +-
.../rule/virtualservice/VirtualServiceSpec.java | 43 +-
.../destination/DubboDestination.java | 59 +
.../destination/DubboRouteDestination.java | 35 +-
.../mesh/rule/virtualservice/match/BoolMatch.java | 33 +-
.../rule/virtualservice/match/DoubleMatch.java | 63 +
.../virtualservice/match/DoubleRangeMatch.java | 53 +
.../virtualservice/match/DubboAttachmentMatch.java | 76 ++
.../rule/virtualservice/match/DubboMethodArg.java | 90 ++
.../virtualservice/match/DubboMethodMatch.java | 128 ++
.../rule/virtualservice/match/ListBoolMatch.java | 21 +-
.../rule/virtualservice/match/ListDoubleMatch.java | 36 +-
.../rule/virtualservice/match/ListStringMatch.java | 37 +-
.../rule/virtualservice/match/StringMatch.java | 105 ++
.../util/VsDestinationGroupRuleDispatcher.java | 53 +
.../mesh/util/VsDestinationGroupRuleListener.java | 22 +-
.../org.apache.dubbo.registry.AddressListener | 1 +
.../org.apache.dubbo.rpc.cluster.RouterFactory | 1 +
.../router/mesh/route/MeshAppRuleListenerTest.java | 180 +++
.../router/mesh/route/MeshRuleManagerTest.java | 160 +++
.../mesh/route/MeshRuleRouterFactoryTest.java | 27 +-
.../router/mesh/route/MeshRuleRouterTest.java | 1407 ++++++++++++++++++++
.../router/mesh/rule/DestinationRuleTest.java | 102 ++
.../router/mesh/rule/VirtualServiceRuleTest.java | 31 +-
.../rule/virtualservice/DubboMatchRequestTest.java | 140 ++
.../rule/virtualservice/match/BoolMatchTest.java | 35 +-
.../rule/virtualservice/match/DoubleMatchTest.java | 101 ++
.../match/DubboAttachmentMatchTest.java | 178 +++
.../virtualservice/match/DubboMethodMatchTest.java | 156 +++
.../virtualservice/match/ListDoubleMatchTest.java | 52 +
.../virtualservice/match/ListStringMatchTest.java | 54 +
.../rule/virtualservice/match/StringMatchTest.java | 81 ++
.../util/VsDestinationGroupRuleDispatcherTest.java | 74 +
.../src/test/resources/DestinationRuleTest.yaml | 33 +
.../src/test/resources/DestinationRuleTest2.yaml | 58 +
.../src/test/resources/VirtualServiceTest.yaml | 41 +
58 files changed, 4780 insertions(+), 344 deletions(-)
diff --git a/dubbo-cluster/pom.xml b/dubbo-cluster/pom.xml
index bd62974..bb58849 100644
--- a/dubbo-cluster/pom.xml
+++ b/dubbo-cluster/pom.xml
@@ -14,7 +14,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.dubbo</groupId>
@@ -39,7 +40,6 @@
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
-
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/registry/AddressListener.java
similarity index 100%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/registry/AddressListener.java
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListener.java
new file mode 100644
index 0000000..3946ba4
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListener.java
@@ -0,0 +1,98 @@
+/*
+ * 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.router.mesh.route;
+
+import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRule;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceRule;
+import org.apache.dubbo.rpc.cluster.router.mesh.util.VsDestinationGroupRuleDispatcher;
+import org.yaml.snakeyaml.Yaml;
+
+import java.text.MessageFormat;
+import java.util.Map;
+
+
+public class MeshAppRuleListener implements ConfigurationListener {
+
+ public static final Logger logger = LoggerFactory.getLogger(MeshAppRuleListener.class);
+
+ private final VsDestinationGroupRuleDispatcher vsDestinationGroupRuleDispatcher = new VsDestinationGroupRuleDispatcher();
+
+ private String appName;
+
+ private VsDestinationGroup vsDestinationGroupHolder;
+
+ public MeshAppRuleListener(String appName) {
+ this.appName = appName;
+ }
+
+ public void receiveConfigInfo(String configInfo) {
+ logger.info(MessageFormat.format("[MeshAppRule] Received rule for app [{0}]: {1}.",
+ appName, configInfo));
+ try {
+
+ VsDestinationGroup vsDestinationGroup = new VsDestinationGroup();
+ vsDestinationGroup.setAppName(appName);
+
+ Yaml yaml = new Yaml();
+ Yaml yaml2 = new Yaml();
+ Iterable objectIterable = yaml.loadAll(configInfo);
+ for (Object result : objectIterable) {
+
+ Map resultMap = (Map) result;
+ if (resultMap.get("kind").equals("DestinationRule")) {
+ DestinationRule destinationRule = yaml2.loadAs(yaml2.dump(result), DestinationRule.class);
+ vsDestinationGroup.getDestinationRuleList().add(destinationRule);
+
+ } else if (resultMap.get("kind").equals("VirtualService")) {
+ VirtualServiceRule virtualServiceRule = yaml2.loadAs(yaml2.dump(result), VirtualServiceRule.class);
+ vsDestinationGroup.getVirtualServiceRuleList().add(virtualServiceRule);
+ }
+ }
+
+ vsDestinationGroupHolder = vsDestinationGroup;
+ } catch (Exception e) {
+ logger.error("[MeshAppRule] parse failed: " + configInfo, e);
+ }
+ if (vsDestinationGroupHolder != null) {
+ vsDestinationGroupRuleDispatcher.post(vsDestinationGroupHolder);
+ }
+
+ }
+
+ public void register(MeshRuleRouter subscriber) {
+ if (vsDestinationGroupHolder != null) {
+ subscriber.onRuleChange(vsDestinationGroupHolder);
+ }
+ vsDestinationGroupRuleDispatcher.register(subscriber);
+ }
+
+ //
+ public void unregister(MeshRuleRouter sub) {
+ vsDestinationGroupRuleDispatcher.unregister(sub);
+ }
+
+ @Override
+ public void process(ConfigChangedEvent event) {
+ receiveConfigInfo(event.getContent());
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleAddressListenerInterceptor.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleAddressListenerInterceptor.java
new file mode 100644
index 0000000..d4cf551
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleAddressListenerInterceptor.java
@@ -0,0 +1,51 @@
+/*
+ * 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.router.mesh.route;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.registry.AddressListener;
+import org.apache.dubbo.rpc.cluster.Directory;
+
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Activate(order = 670)
+public class MeshRuleAddressListenerInterceptor implements AddressListener {
+
+ private static final Object mark = new Object();
+ private static ConcurrentHashMap<String, Object> appMap = new ConcurrentHashMap<String, Object>();
+
+ @Override
+ public List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory) {
+
+ if (addresses != null && !addresses.isEmpty()) {
+ for (URL serviceURL : addresses) {
+
+ String app = serviceURL.getRemoteApplication();
+ if (app != null && !app.isEmpty()) {
+ if (appMap.putIfAbsent(app, mark) == null) {
+ MeshRuleManager.subscribeAppRule(app);
+ }
+ }
+ }
+ }
+
+ return addresses;
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManager.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManager.java
new file mode 100644
index 0000000..aa1630f
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManager.java
@@ -0,0 +1,79 @@
+/*
+ * 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.router.mesh.route;
+
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
+import java.util.Collection;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+public final class MeshRuleManager {
+
+ public static final Logger logger = LoggerFactory.getLogger(MeshRuleManager.class);
+
+ private static final String MESH_RULE_DATA_ID_SUFFIX = ".MESHAPPRULE";
+ private static final String GROUP = "DEFAULT_GROUP";
+
+ private static ConcurrentHashMap<String, MeshAppRuleListener> appRuleListeners = new ConcurrentHashMap<>();
+
+ public synchronized static void subscribeAppRule(String app) {
+
+ MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener(app);
+ String appRuleDataId = app + MESH_RULE_DATA_ID_SUFFIX;
+ DynamicConfiguration configuration = ApplicationModel.getEnvironment().getDynamicConfiguration()
+ .orElse(null);
+
+ if (configuration == null) {
+ logger.warn("Doesn't support DynamicConfiguration!");
+ return;
+ }
+
+ try {
+ String rawConfig = configuration.getConfig(appRuleDataId, GROUP, 5000L);
+ if (rawConfig != null) {
+ meshAppRuleListener.receiveConfigInfo(rawConfig);
+ }
+ } catch (Throwable throwable) {
+ logger.error("get MeshRuleManager app rule failed.", throwable);
+ }
+
+ configuration.addListener(appRuleDataId, GROUP, meshAppRuleListener);
+ appRuleListeners.put(app, meshAppRuleListener);
+ }
+
+ public static void register(String app, MeshRuleRouter subscriber) {
+ MeshAppRuleListener meshAppRuleListener = appRuleListeners.get(app);
+ if (meshAppRuleListener == null) {
+ logger.warn("appRuleListener can't find when Router register");
+ return;
+ }
+ meshAppRuleListener.register(subscriber);
+ }
+
+ public static void unregister(MeshRuleRouter subscriber) {
+ Collection<MeshAppRuleListener> listeners = appRuleListeners.values();
+ for (MeshAppRuleListener listener : listeners) {
+ listener.unregister(subscriber);
+ }
+ }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouter.java
new file mode 100644
index 0000000..34b9e7f
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouter.java
@@ -0,0 +1,359 @@
+/*
+ * 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.router.mesh.route;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Router;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRule;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRuleSpec;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.Subset;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.DubboMatchRequest;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.DubboRoute;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.DubboRouteDetail;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceRule;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceSpec;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination.DubboDestination;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination.DubboRouteDestination;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
+import org.apache.dubbo.rpc.cluster.router.mesh.util.VsDestinationGroupRuleListener;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+
+public class MeshRuleRouter implements Router, VsDestinationGroupRuleListener {
+
+ protected int priority = -500;
+ protected boolean force = false;
+ protected URL url;
+
+ private VsDestinationGroup vsDestinationGroup;
+
+ private Map<String, String> sourcesLables = new HashMap<>();
+
+ protected List<Invoker<?>> invokerList = new ArrayList<>();
+
+ Map<String, List<Invoker<?>>> subsetMap;
+
+ private String remoteAppName;
+
+ public MeshRuleRouter(URL url) {
+ this.url = url;
+ sourcesLables.putAll(url.getParameters());
+ }
+
+ @Override
+ public URL getUrl() {
+ return url;
+ }
+
+ @Override
+ public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
+
+ List<DubboRouteDestination> routeDestination = getDubboRouteDestination(invocation);
+
+ if (routeDestination == null) {
+ return invokers;
+ } else {
+ Random random = new Random();
+ int index = random.nextInt(routeDestination.size());
+ DubboRouteDestination dubboRouteDestination = routeDestination.get(index);
+
+ DubboDestination dubboDestination = dubboRouteDestination.getDestination();
+
+ String host = dubboDestination.getHost();
+ String subset = dubboDestination.getSubset();
+
+ List<Invoker<?>> result;
+
+ Map<String, List<Invoker<?>>> subsetMapCopy = this.subsetMap;
+
+ //TODO make intersection with invokers
+ if (subsetMapCopy != null) {
+
+ do {
+ result = subsetMapCopy.get(subset);
+
+ if (result != null && result.size() > 0) {
+ return (List) result;
+ }
+
+ dubboRouteDestination = dubboDestination.getFallback();
+ if (dubboRouteDestination == null) {
+ break;
+ }
+ dubboDestination = dubboRouteDestination.getDestination();
+
+ host = dubboDestination.getHost();
+ subset = dubboDestination.getSubset();
+ } while (true);
+
+ return null;
+ }
+ }
+
+ return invokers;
+ }
+
+ @Override
+ public <T> void notify(List<Invoker<T>> invokers) {
+ List invokerList = invokers == null ? Collections.emptyList() : invokers;
+ this.invokerList = invokerList;
+ registerAppRule(invokerList);
+ computeSubset();
+ }
+
+
+ private void registerAppRule(List<Invoker<?>> invokers) {
+ if (StringUtils.isEmpty(remoteAppName)) {
+ synchronized (this) {
+ if (StringUtils.isEmpty(remoteAppName) && invokers != null && invokers.size() > 0) {
+ for (Invoker invoker : invokers) {
+ String applicationName = invoker.getUrl().getRemoteApplication();
+ if (StringUtils.isNotEmpty(applicationName) && !"unknown".equals(applicationName)) {
+ remoteAppName = applicationName;
+ MeshRuleManager.register(remoteAppName, this);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ public void onRuleChange(VsDestinationGroup vsDestinationGroup) {
+ this.vsDestinationGroup = vsDestinationGroup;
+ computeSubset();
+ }
+
+ @Override
+ public boolean isRuntime() {
+ return true;
+ }
+
+ @Override
+ public boolean isForce() {
+ return force;
+ }
+
+ @Override
+ public int getPriority() {
+ return priority;
+ }
+
+ private List<DubboRouteDestination> getDubboRouteDestination(Invocation invocation) {
+
+ if (vsDestinationGroup != null) {
+
+ List<VirtualServiceRule> virtualServiceRuleList = vsDestinationGroup.getVirtualServiceRuleList();
+ if (virtualServiceRuleList.size() > 0) {
+ for (VirtualServiceRule virtualServiceRule : virtualServiceRuleList) {
+ DubboRoute dubboRoute = getDubboRoute(virtualServiceRule, invocation);
+ if (dubboRoute != null) {
+ return getDubboRouteDestination(dubboRoute, invocation);
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ protected DubboRoute getDubboRoute(VirtualServiceRule virtualServiceRule, Invocation invocation) {
+ String serviceName = invocation.getServiceName();
+
+ VirtualServiceSpec spec = virtualServiceRule.getSpec();
+ List<DubboRoute> dubboRouteList = spec.getDubbo();
+ if (dubboRouteList.size() > 0) {
+ for (DubboRoute dubboRoute : dubboRouteList) {
+ List<StringMatch> stringMatchList = dubboRoute.getServices();
+ if (stringMatchList == null || stringMatchList.size() == 0) {
+ return dubboRoute;
+ }
+ for (StringMatch stringMatch : stringMatchList) {
+ if (StringMatch.isMatch(stringMatch, serviceName)) {
+ return dubboRoute;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+
+ protected List<DubboRouteDestination> getDubboRouteDestination(DubboRoute dubboRoute, Invocation invocation) {
+
+ List<DubboRouteDetail> dubboRouteDetailList = dubboRoute.getRoutedetail();
+ if (dubboRouteDetailList.size() > 0) {
+ DubboRouteDetail dubboRouteDetail = findMatchDubboRouteDetail(dubboRouteDetailList, invocation);
+ if (dubboRouteDetail != null) {
+ return dubboRouteDetail.getRoute();
+ }
+ }
+
+ return null;
+ }
+
+ protected DubboRouteDetail findMatchDubboRouteDetail(List<DubboRouteDetail> dubboRouteDetailList, Invocation invocation) {
+
+ String methodName = invocation.getMethodName();
+ String[] parameterTypeList = invocation.getCompatibleParamSignatures();
+ Object[] parameters = invocation.getArguments();
+
+
+ for (DubboRouteDetail dubboRouteDetail : dubboRouteDetailList) {
+ List<DubboMatchRequest> matchRequestList = dubboRouteDetail.getMatch();
+ if (matchRequestList == null || matchRequestList.size() == 0) {
+ return dubboRouteDetail;
+ }
+
+ boolean match = true;
+
+ //FIXME to deal with headers
+ for (DubboMatchRequest dubboMatchRequest : matchRequestList) {
+ if (!DubboMatchRequest.isMatch(dubboMatchRequest, methodName, parameterTypeList, parameters,
+ sourcesLables,
+ new HashMap<>(), invocation.getAttachments(),
+ new HashMap<>())) {
+ match = false;
+ break;
+ }
+ }
+
+ if (match) {
+ return dubboRouteDetail;
+ }
+ }
+ return null;
+ }
+
+
+ protected synchronized void computeSubset() {
+ if (invokerList == null || invokerList.size() == 0) {
+ this.subsetMap = null;
+ return;
+ }
+
+ if (vsDestinationGroup == null) {
+ this.subsetMap = null;
+ return;
+ }
+
+ Map<String, List<Invoker<?>>> subsetMap = computeSubsetMap(invokerList, vsDestinationGroup.getDestinationRuleList());
+
+ if (subsetMap.size() == 0) {
+ this.subsetMap = null;
+ } else {
+ this.subsetMap = subsetMap;
+ }
+ }
+
+
+ protected Map<String, List<Invoker<?>>> computeSubsetMap(List<Invoker<?>> invokers, List<DestinationRule> destinationRules) {
+ Map<String, List<Invoker<?>>> subsetMap = new HashMap<>();
+
+ for (DestinationRule destinationRule : destinationRules) {
+ DestinationRuleSpec destinationRuleSpec = destinationRule.getSpec();
+ String host = destinationRuleSpec.getHost();
+ List<Subset> subsetList = destinationRuleSpec.getSubsets();
+
+ for (Subset subset : subsetList) {
+ String subsetName = subset.getName();
+ List<Invoker<?>> subsetInvokerList = new ArrayList<>();
+ subsetMap.put(subsetName, subsetInvokerList);
+
+ Map<String, String> labels = subset.getLabels();
+
+ for (Invoker<?> invoker : invokers) {
+ Map<String, String> parameters = invoker.getUrl().getParameters();
+ if (containMapKeyValue(parameters, labels)) {
+ subsetInvokerList.add(invoker);
+ }
+ }
+ }
+ }
+
+ return subsetMap;
+ }
+
+
+ protected boolean containMapKeyValue(Map<String, String> originMap, Map<String, String> inputMap) {
+ if (inputMap == null || inputMap.size() == 0) {
+ return true;
+ }
+
+ for (Map.Entry<String, String> entry : inputMap.entrySet()) {
+ String key = entry.getKey();
+ String value = entry.getValue();
+
+ String originMapValue = originMap.get(key);
+ if (!value.equals(originMapValue)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ // just for test
+ protected void setVsDestinationGroup(VsDestinationGroup vsDestinationGroup) {
+ this.vsDestinationGroup = vsDestinationGroup;
+ }
+
+ // just for test
+ protected void setSourcesLables(Map<String, String> sourcesLables) {
+ this.sourcesLables = sourcesLables;
+ }
+
+ // just for test
+ protected void setInvokerList(List<Invoker<?>> invokerList) {
+ this.invokerList = invokerList;
+ }
+
+ // just for test
+ protected void setSubsetMap(Map<String, List<Invoker<?>>> subsetMap) {
+ this.subsetMap = subsetMap;
+ }
+
+
+ public VsDestinationGroup getVsDestinationGroup() {
+ return vsDestinationGroup;
+ }
+
+ public Map<String, String> getSourcesLables() {
+ return sourcesLables;
+ }
+
+ public List<Invoker<?>> getInvokerList() {
+ return invokerList;
+ }
+
+ public Map<String, List<Invoker<?>>> getSubsetMap() {
+ return subsetMap;
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactory.java
similarity index 64%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactory.java
index ff77800..fdbe8e9 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactory.java
@@ -14,24 +14,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
-
-import java.util.List;
+package org.apache.dubbo.rpc.cluster.router.mesh.route;
-@SPI
-public interface AddressListener {
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.rpc.cluster.Router;
+import org.apache.dubbo.rpc.cluster.RouterFactory;
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
-}
\ No newline at end of file
+@Activate(order = -50)
+public class MeshRuleRouterFactory implements RouterFactory {
+ @Override
+ public Router getRouter(URL url) {
+ return new MeshRuleRouter(url);
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/BaseRule.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/BaseRule.java
new file mode 100644
index 0000000..ffb236f
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/BaseRule.java
@@ -0,0 +1,60 @@
+/*
+ * 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.router.mesh.rule;
+
+import java.util.Map;
+
+
+public class BaseRule {
+ private String apiVersion;
+ private String kind;
+ private Map<String,String> metadata;
+
+ public String getApiVersion() {
+ return apiVersion;
+ }
+
+ public void setApiVersion(String apiVersion) {
+ this.apiVersion = apiVersion;
+ }
+
+ public String getKind() {
+ return kind;
+ }
+
+ public void setKind(String kind) {
+ this.kind = kind;
+ }
+
+ public Map<String, String> getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(Map<String, String> metadata) {
+ this.metadata = metadata;
+ }
+
+ @Override
+ public String toString() {
+ return "BaseRule{" +
+ "apiVersion='" + apiVersion + '\'' +
+ ", kind='" + kind + '\'' +
+ ", metadata=" + metadata +
+ '}';
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VsDestinationGroup.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VsDestinationGroup.java
new file mode 100644
index 0000000..1d310ee
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VsDestinationGroup.java
@@ -0,0 +1,55 @@
+/*
+ * 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.router.mesh.rule;
+
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRule;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class VsDestinationGroup {
+ private String appName;
+ private List<VirtualServiceRule> virtualServiceRuleList = new ArrayList<>();
+ private List<DestinationRule> destinationRuleList = new ArrayList<>();
+
+ public String getAppName() {
+ return appName;
+ }
+
+ public void setAppName(String appName) {
+ this.appName = appName;
+ }
+
+ public List<VirtualServiceRule> getVirtualServiceRuleList() {
+ return virtualServiceRuleList;
+ }
+
+ public void setVirtualServiceRuleList(List<VirtualServiceRule> virtualServiceRuleList) {
+ this.virtualServiceRuleList = virtualServiceRuleList;
+ }
+
+ public List<DestinationRule> getDestinationRuleList() {
+ return destinationRuleList;
+ }
+
+ public void setDestinationRuleList(List<DestinationRule> destinationRuleList) {
+ this.destinationRuleList = destinationRuleList;
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/ConnectionPoolSettings.java
similarity index 61%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/ConnectionPoolSettings.java
index ff77800..32b7af9 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/ConnectionPoolSettings.java
@@ -14,24 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
-import java.util.List;
-@SPI
-public interface AddressListener {
-
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
-
-}
\ No newline at end of file
+public class ConnectionPoolSettings {
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/DestinationRule.java
similarity index 58%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/DestinationRule.java
index ff77800..42bc049 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/DestinationRule.java
@@ -14,24 +14,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
-import java.util.List;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.BaseRule;
-@SPI
-public interface AddressListener {
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+public class DestinationRule extends BaseRule {
+ private DestinationRuleSpec spec;
-}
\ No newline at end of file
+ public DestinationRuleSpec getSpec() {
+ return spec;
+ }
+
+ public void setSpec(DestinationRuleSpec spec) {
+ this.spec = spec;
+ }
+
+ @Override
+ public String toString() {
+ return "DestinationRule{" +
+ "base=" + super.toString() +
+ ", spec=" + spec +
+ '}';
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/DestinationRuleSpec.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/DestinationRuleSpec.java
new file mode 100644
index 0000000..57d8b06
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/DestinationRuleSpec.java
@@ -0,0 +1,60 @@
+/*
+ * 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.router.mesh.rule.destination;
+
+import java.util.List;
+
+
+public class DestinationRuleSpec {
+ private String host;
+ private List<Subset> subsets;
+ private TrafficPolicy trafficPolicy;
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public List<Subset> getSubsets() {
+ return subsets;
+ }
+
+ public void setSubsets(List<Subset> subsets) {
+ this.subsets = subsets;
+ }
+
+ public TrafficPolicy getTrafficPolicy() {
+ return trafficPolicy;
+ }
+
+ public void setTrafficPolicy(TrafficPolicy trafficPolicy) {
+ this.trafficPolicy = trafficPolicy;
+ }
+
+ @Override
+ public String toString() {
+ return "DestinationRuleSpec{" +
+ "host='" + host + '\'' +
+ ", subsets=" + subsets +
+ ", trafficPolicy=" + trafficPolicy +
+ '}';
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/Subset.java
similarity index 55%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/Subset.java
index ff77800..9438ec4 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/Subset.java
@@ -14,24 +14,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
-import java.util.List;
+import java.util.Map;
-@SPI
-public interface AddressListener {
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+public class Subset {
+ private String name;
+ private Map<String, String> labels;
-}
\ No newline at end of file
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Map<String, String> getLabels() {
+ return labels;
+ }
+
+ public void setLabels(Map<String, String> labels) {
+ this.labels = labels;
+ }
+
+ @Override
+ public String toString() {
+ return "Subset{" +
+ "name='" + name + '\'' +
+ ", labels=" + labels +
+ '}';
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TCPSettings.java
similarity index 61%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TCPSettings.java
index ff77800..09dc93a 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TCPSettings.java
@@ -14,24 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
-import java.util.List;
-@SPI
-public interface AddressListener {
-
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
-
-}
\ No newline at end of file
+public class TCPSettings {
+ private int maxConnections;
+ private int connectTimeout;
+ private TcpKeepalive tcpKeepalive;
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TcpKeepalive.java
similarity index 61%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TcpKeepalive.java
index ff77800..3bc43c7 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TcpKeepalive.java
@@ -14,24 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
-import java.util.List;
-@SPI
-public interface AddressListener {
+public class TcpKeepalive {
+ private int probes;
+ private int time;
+ private int interval;
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
-
-}
\ No newline at end of file
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TrafficPolicy.java
similarity index 57%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TrafficPolicy.java
index ff77800..7f771f0 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TrafficPolicy.java
@@ -14,24 +14,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
-import java.util.List;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance.LoadBalancerSettings;
-@SPI
-public interface AddressListener {
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+public class TrafficPolicy {
+ private LoadBalancerSettings loadBalancer;
-}
\ No newline at end of file
+ public LoadBalancerSettings getLoadBalancer() {
+ return loadBalancer;
+ }
+
+ public void setLoadBalancer(LoadBalancerSettings loadBalancer) {
+ this.loadBalancer = loadBalancer;
+ }
+
+ @Override
+ public String toString() {
+ return "TrafficPolicy{" +
+ "loadBalancer=" + loadBalancer +
+ '}';
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/ConsistentHashLB.java
similarity index 61%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/ConsistentHashLB.java
index ff77800..213dfee 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/ConsistentHashLB.java
@@ -14,24 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance;
-import java.util.List;
-@SPI
-public interface AddressListener {
-
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
-
-}
\ No newline at end of file
+public class ConsistentHashLB {
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/LoadBalancerSettings.java
similarity index 51%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/LoadBalancerSettings.java
index ff77800..1f8b60e 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/LoadBalancerSettings.java
@@ -14,24 +14,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance;
-import java.util.List;
-@SPI
-public interface AddressListener {
+public class LoadBalancerSettings {
+ private SimpleLB simple;
+ private ConsistentHashLB consistentHash;
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+ public SimpleLB getSimple() {
+ return simple;
+ }
-}
\ No newline at end of file
+ public void setSimple(SimpleLB simple) {
+ this.simple = simple;
+ }
+
+ public ConsistentHashLB getConsistentHash() {
+ return consistentHash;
+ }
+
+ public void setConsistentHash(ConsistentHashLB consistentHash) {
+ this.consistentHash = consistentHash;
+ }
+
+ @Override
+ public String toString() {
+ return "LoadBalancerSettings{" +
+ "simple=" + simple +
+ ", consistentHash=" + consistentHash +
+ '}';
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/SimpleLB.java
similarity index 61%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/SimpleLB.java
index ff77800..003f1f6 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/SimpleLB.java
@@ -14,24 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance;
-import java.util.List;
-@SPI
-public interface AddressListener {
-
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
-
-}
\ No newline at end of file
+public enum SimpleLB {
+ ROUND_ROBIN,
+ LEAST_CONN,
+ RANDOM,
+ PASSTHROUGH
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequest.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequest.java
new file mode 100644
index 0000000..832bdfe
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.router.mesh.rule.virtualservice;
+
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.DoubleMatch;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.DubboAttachmentMatch;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.DubboMethodMatch;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
+
+import java.util.Map;
+
+
+public class DubboMatchRequest {
+ private String name;
+ private DubboMethodMatch method;
+ private Map<String, String> sourceLabels;
+ private DubboAttachmentMatch attachments;
+ private Map<String, StringMatch> headers;
+ private DoubleMatch threshold;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public DubboMethodMatch getMethod() {
+ return method;
+ }
+
+ public void setMethod(DubboMethodMatch method) {
+ this.method = method;
+ }
+
+ public Map<String, String> getSourceLabels() {
+ return sourceLabels;
+ }
+
+ public void setSourceLabels(Map<String, String> sourceLabels) {
+ this.sourceLabels = sourceLabels;
+ }
+
+ public DubboAttachmentMatch getAttachments() {
+ return attachments;
+ }
+
+ public void setAttachments(DubboAttachmentMatch attachments) {
+ this.attachments = attachments;
+ }
+
+ public Map<String, StringMatch> getHeaders() {
+ return headers;
+ }
+
+ public void setHeaders(Map<String, StringMatch> headers) {
+ this.headers = headers;
+ }
+
+ public DoubleMatch getThreshold() {
+ return threshold;
+ }
+
+ public void setThreshold(DoubleMatch threshold) {
+ this.threshold = threshold;
+ }
+
+
+ public static boolean isMatch(DubboMatchRequest dubboMatchRequest,
+ String methodName, String[] parameterTypeList, Object[] parameters,
+ Map<String, String> sourceLabels,
+ Map<String, String> eagleeyeContext, Map<String, String> dubboContext,
+ Map<String, String> headers
+ ) {
+ if (dubboMatchRequest.getMethod() != null) {
+ if (!DubboMethodMatch.isMatch(dubboMatchRequest.getMethod(), methodName, parameterTypeList, parameters)) {
+ return false;
+ }
+ }
+
+ if (dubboMatchRequest.getSourceLabels() != null) {
+ for (Map.Entry<String, String> entry : dubboMatchRequest.getSourceLabels().entrySet()) {
+ String value = sourceLabels.get(entry.getKey());
+ if (value == null || !entry.getValue().equals(value)) {
+ return false;
+ }
+ }
+ }
+
+ if (dubboMatchRequest.getAttachments() != null) {
+ if (!DubboAttachmentMatch.isMatch(dubboMatchRequest.getAttachments(),eagleeyeContext,dubboContext)){
+ return false;
+ }
+ }
+
+ //TODO headers
+
+
+ return true;
+
+ }
+
+ @Override
+ public String toString() {
+ return "DubboMatchRequest{" +
+ "name='" + name + '\'' +
+ ", method=" + method +
+ ", sourceLabels=" + sourceLabels +
+ ", attachments=" + attachments +
+ ", headers=" + headers +
+ ", threshold=" + threshold +
+ '}';
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboRoute.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboRoute.java
new file mode 100644
index 0000000..d6bf124
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboRoute.java
@@ -0,0 +1,62 @@
+/*
+ * 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.router.mesh.rule.virtualservice;
+
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
+
+import java.util.List;
+
+
+public class DubboRoute {
+ private String name;
+ private List<StringMatch> services;
+ private List<DubboRouteDetail> routedetail;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List<StringMatch> getServices() {
+ return services;
+ }
+
+ public void setServices(List<StringMatch> services) {
+ this.services = services;
+ }
+
+ public List<DubboRouteDetail> getRoutedetail() {
+ return routedetail;
+ }
+
+ public void setRoutedetail(List<DubboRouteDetail> routedetail) {
+ this.routedetail = routedetail;
+ }
+
+ @Override
+ public String toString() {
+ return "DubboRoute{" +
+ "name='" + name + '\'' +
+ ", services=" + services +
+ ", routedetail=" + routedetail +
+ '}';
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboRouteDetail.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboRouteDetail.java
new file mode 100644
index 0000000..ce42591
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboRouteDetail.java
@@ -0,0 +1,62 @@
+/*
+ * 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.router.mesh.rule.virtualservice;
+
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination.DubboRouteDestination;
+
+import java.util.List;
+
+
+public class DubboRouteDetail {
+ private String name;
+ private List<DubboMatchRequest> match;
+ private List<DubboRouteDestination> route;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List<DubboMatchRequest> getMatch() {
+ return match;
+ }
+
+ public void setMatch(List<DubboMatchRequest> match) {
+ this.match = match;
+ }
+
+ public List<DubboRouteDestination> getRoute() {
+ return route;
+ }
+
+ public void setRoute(List<DubboRouteDestination> route) {
+ this.route = route;
+ }
+
+ @Override
+ public String toString() {
+ return "DubboRouteDetail{" +
+ "name='" + name + '\'' +
+ ", match=" + match +
+ ", route=" + route +
+ '}';
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceRule.java
similarity index 58%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceRule.java
index ff77800..8f5497a 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceRule.java
@@ -14,24 +14,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
-import java.util.List;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.BaseRule;
-@SPI
-public interface AddressListener {
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+public class VirtualServiceRule extends BaseRule {
+ private VirtualServiceSpec spec;
-}
\ No newline at end of file
+ public VirtualServiceSpec getSpec() {
+ return spec;
+ }
+
+ public void setSpec(VirtualServiceSpec spec) {
+ this.spec = spec;
+ }
+
+ @Override
+ public String toString() {
+ return "VirtualServiceRule{" +
+ "base=" + super.toString() +
+ ", spec=" + spec +
+ '}';
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceSpec.java
similarity index 55%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceSpec.java
index ff77800..648fe3b 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceSpec.java
@@ -14,24 +14,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
import java.util.List;
-@SPI
-public interface AddressListener {
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+public class VirtualServiceSpec {
+ private List<String> hosts;
+ private List<DubboRoute> dubbo;
-}
\ No newline at end of file
+ public List<String> getHosts() {
+ return hosts;
+ }
+
+ public void setHosts(List<String> hosts) {
+ this.hosts = hosts;
+ }
+
+ public List<DubboRoute> getDubbo() {
+ return dubbo;
+ }
+
+ public void setDubbo(List<DubboRoute> dubbo) {
+ this.dubbo = dubbo;
+ }
+
+ @Override
+ public String toString() {
+ return "VirtualServiceSpec{" +
+ "hosts=" + hosts +
+ ", dubbo=" + dubbo +
+ '}';
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/destination/DubboDestination.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/destination/DubboDestination.java
new file mode 100644
index 0000000..c21a008
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/destination/DubboDestination.java
@@ -0,0 +1,59 @@
+/*
+ * 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.router.mesh.rule.virtualservice.destination;
+
+
+public class DubboDestination {
+ private String host;
+ private String subset;
+ private int port;
+ private DubboRouteDestination fallback;
+
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public String getSubset() {
+ return subset;
+ }
+
+ public void setSubset(String subset) {
+ this.subset = subset;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public DubboRouteDestination getFallback() {
+ return fallback;
+ }
+
+ public void setFallback(DubboRouteDestination fallback) {
+ this.fallback = fallback;
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/destination/DubboRouteDestination.java
similarity index 61%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/destination/DubboRouteDestination.java
index ff77800..b9588c4 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/destination/DubboRouteDestination.java
@@ -14,24 +14,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination;
-import java.util.List;
-@SPI
-public interface AddressListener {
+public class DubboRouteDestination {
+ private DubboDestination destination;
+ private int weight;
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+ public DubboDestination getDestination() {
+ return destination;
+ }
-}
\ No newline at end of file
+ public void setDestination(DubboDestination destination) {
+ this.destination = destination;
+ }
+
+ public int getWeight() {
+ return weight;
+ }
+
+ public void setWeight(int weight) {
+ this.weight = weight;
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatch.java
similarity index 61%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatch.java
index ff77800..6d76054 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatch.java
@@ -14,24 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
-import java.util.List;
-@SPI
-public interface AddressListener {
+public class BoolMatch {
+ private Boolean exact;
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+ public Boolean getExact() {
+ return exact;
+ }
-}
\ No newline at end of file
+ public void setExact(Boolean exact) {
+ this.exact = exact;
+ }
+
+ public static boolean isMatch(BoolMatch boolMatch,boolean input){
+ if (boolMatch.getExact() != null){
+ return input == boolMatch.getExact();
+ }
+ return false;
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatch.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatch.java
new file mode 100644
index 0000000..2bd094e
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatch.java
@@ -0,0 +1,63 @@
+/*
+ * 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.router.mesh.rule.virtualservice.match;
+
+
+public class DoubleMatch {
+ private Double exact;
+ private DoubleRangeMatch range;
+ private Double mod;
+
+ public Double getExact() {
+ return exact;
+ }
+
+ public void setExact(Double exact) {
+ this.exact = exact;
+ }
+
+ public DoubleRangeMatch getRange() {
+ return range;
+ }
+
+ public void setRange(DoubleRangeMatch range) {
+ this.range = range;
+ }
+
+ public Double getMod() {
+ return mod;
+ }
+
+ public void setMod(Double mod) {
+ this.mod = mod;
+ }
+
+
+ public static boolean isMatch(DoubleMatch doubleMatch, Double input) {
+ if (doubleMatch.getExact() != null && doubleMatch.getMod() == null) {
+ return input.equals(doubleMatch.getExact());
+ } else if (doubleMatch.getRange() != null) {
+ return DoubleRangeMatch.isMatch(doubleMatch.getRange(), input);
+ } else if (doubleMatch.getExact() != null && doubleMatch.getMod() != null) {
+ Double result = input % doubleMatch.getMod();
+ return result.equals(doubleMatch.getExact());
+ }
+
+ return false;
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleRangeMatch.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleRangeMatch.java
new file mode 100644
index 0000000..dd69338
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleRangeMatch.java
@@ -0,0 +1,53 @@
+/*
+ * 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.router.mesh.rule.virtualservice.match;
+
+
+public class DoubleRangeMatch {
+ private Double start;
+ private Double end;
+
+ public Double getStart() {
+ return start;
+ }
+
+ public void setStart(Double start) {
+ this.start = start;
+ }
+
+ public Double getEnd() {
+ return end;
+ }
+
+ public void setEnd(Double end) {
+ this.end = end;
+ }
+
+
+ public static boolean isMatch(DoubleRangeMatch doubleRangeMatch, Double input) {
+ if (doubleRangeMatch.getStart() != null && doubleRangeMatch.getEnd() != null) {
+ return input.compareTo(doubleRangeMatch.getStart()) >= 0 && input.compareTo(doubleRangeMatch.getEnd()) < 0;
+ } else if (doubleRangeMatch.getStart() != null) {
+ return input.compareTo(doubleRangeMatch.getStart()) >= 0;
+ } else if (doubleRangeMatch.getEnd() != null) {
+ return input.compareTo(doubleRangeMatch.getEnd()) < 0;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatch.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatch.java
new file mode 100644
index 0000000..b368e5b
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatch.java
@@ -0,0 +1,76 @@
+/*
+ * 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.router.mesh.rule.virtualservice.match;
+
+import java.util.Map;
+
+
+public class DubboAttachmentMatch {
+ private Map<String, StringMatch> eagleeyecontext;
+ private Map<String, StringMatch> dubbocontext;
+
+ public Map<String, StringMatch> getEagleeyecontext() {
+ return eagleeyecontext;
+ }
+
+ public void setEagleeyecontext(Map<String, StringMatch> eagleeyecontext) {
+ this.eagleeyecontext = eagleeyecontext;
+ }
+
+ public Map<String, StringMatch> getDubbocontext() {
+ return dubbocontext;
+ }
+
+ public void setDubbocontext(Map<String, StringMatch> dubbocontext) {
+ this.dubbocontext = dubbocontext;
+ }
+
+ public static boolean isMatch(DubboAttachmentMatch dubboAttachmentMatch, Map<String, String> eagleeyeContext, Map<String, String> dubboContext) {
+ if (dubboAttachmentMatch.getDubbocontext() != null) {
+ for (Map.Entry<String, StringMatch> stringStringMatchEntry : dubboAttachmentMatch.getDubbocontext().entrySet()) {
+ String key = stringStringMatchEntry.getKey();
+ StringMatch stringMatch = stringStringMatchEntry.getValue();
+
+ String dubboContextValue = dubboContext.get(key);
+ if (dubboContextValue == null) {
+ return false;
+ }
+ if (!StringMatch.isMatch(stringMatch, dubboContextValue)) {
+ return false;
+ }
+ }
+ }
+
+ if (dubboAttachmentMatch.getEagleeyecontext() != null) {
+ for (Map.Entry<String, StringMatch> stringStringMatchEntry : dubboAttachmentMatch.getEagleeyecontext().entrySet()) {
+ String key = stringStringMatchEntry.getKey();
+ StringMatch stringMatch = stringStringMatchEntry.getValue();
+
+ String eagleeyeContextValue = eagleeyeContext.get(key);
+ if (eagleeyeContextValue == null) {
+ return false;
+ }
+ if (!StringMatch.isMatch(stringMatch, eagleeyeContextValue)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodArg.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodArg.java
new file mode 100644
index 0000000..5d21572
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodArg.java
@@ -0,0 +1,90 @@
+/*
+ * 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.router.mesh.rule.virtualservice.match;
+
+
+public class DubboMethodArg {
+ private int index;
+ private String type;
+ private ListStringMatch str_value;
+ private ListDoubleMatch num_value;
+ private BoolMatch bool_value;
+
+ public int getIndex() {
+ return index;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public ListStringMatch getStr_value() {
+ return str_value;
+ }
+
+ public void setStr_value(ListStringMatch str_value) {
+ this.str_value = str_value;
+ }
+
+ public ListDoubleMatch getNum_value() {
+ return num_value;
+ }
+
+ public void setNum_value(ListDoubleMatch num_value) {
+ this.num_value = num_value;
+ }
+
+ public BoolMatch getBool_value() {
+ return bool_value;
+ }
+
+ public void setBool_value(BoolMatch bool_value) {
+ this.bool_value = bool_value;
+ }
+
+ public static boolean isMatch(DubboMethodArg dubboMethodArg, Object input) {
+
+ if (dubboMethodArg.getStr_value() != null) {
+ return ListStringMatch.isMatch(dubboMethodArg.getStr_value(), (String) input);
+ } else if (dubboMethodArg.getNum_value() != null) {
+ return ListDoubleMatch.isMatch(dubboMethodArg.getNum_value(), Double.valueOf(input.toString()));
+ } else if (dubboMethodArg.getBool_value() != null) {
+ return BoolMatch.isMatch(dubboMethodArg.getBool_value(), (Boolean) input);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "DubboMethodArg{" +
+ "index=" + index +
+ ", type='" + type + '\'' +
+ ", str_value=" + str_value +
+ ", num_value=" + num_value +
+ ", bool_value=" + bool_value +
+ '}';
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatch.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatch.java
new file mode 100644
index 0000000..e68ea40
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatch.java
@@ -0,0 +1,128 @@
+/*
+ * 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.router.mesh.rule.virtualservice.match;
+
+import java.util.List;
+import java.util.Map;
+
+
+public class DubboMethodMatch {
+ private StringMatch name_match;
+ private Integer argc;
+ private List<DubboMethodArg> args;
+ private List<StringMatch> argp;
+ private Map<String, StringMatch> headers;
+
+ public StringMatch getName_match() {
+ return name_match;
+ }
+
+ public void setName_match(StringMatch name_match) {
+ this.name_match = name_match;
+ }
+
+ public Integer getArgc() {
+ return argc;
+ }
+
+ public void setArgc(Integer argc) {
+ this.argc = argc;
+ }
+
+ public List<DubboMethodArg> getArgs() {
+ return args;
+ }
+
+ public void setArgs(List<DubboMethodArg> args) {
+ this.args = args;
+ }
+
+ public List<StringMatch> getArgp() {
+ return argp;
+ }
+
+ public void setArgp(List<StringMatch> argp) {
+ this.argp = argp;
+ }
+
+ public Map<String, StringMatch> getHeaders() {
+ return headers;
+ }
+
+ public void setHeaders(Map<String, StringMatch> headers) {
+ this.headers = headers;
+ }
+
+ public static boolean isMatch(DubboMethodMatch dubboMethodMatch, String methodName, String[] parameterTypeList, Object[] parameters) {
+ StringMatch nameMatch = dubboMethodMatch.getName_match();
+ if (nameMatch != null && !StringMatch.isMatch(nameMatch, methodName)) {
+ return false;
+ }
+
+ Integer argc = dubboMethodMatch.getArgc();
+ if (argc != null &&
+ ((argc != 0 && (parameters == null || parameters.length == 0)) || (argc != parameters.length))) {
+ return false;
+ }
+ List<StringMatch> argp = dubboMethodMatch.getArgp();
+ if (argp != null) {
+ if (((parameterTypeList == null || parameterTypeList.length == 0) && argp.size() > 0)
+ || (argp.size() != parameterTypeList.length)) {
+ return false;
+ }
+
+ for (int index = 0; index < argp.size(); index++) {
+ if (!StringMatch.isMatch(argp.get(index), parameterTypeList[index])) {
+ return false;
+ }
+ }
+ }
+
+ List<DubboMethodArg> args = dubboMethodMatch.getArgs();
+
+ if (args != null && args.size() > 0) {
+ if (parameters == null || parameters.length == 0) {
+ return false;
+ }
+
+ for (DubboMethodArg dubboMethodArg : args) {
+ int index = dubboMethodArg.getIndex();
+ if (index >= parameters.length) {
+ throw new IndexOutOfBoundsException("DubboMethodArg index >= parameters.length");
+ }
+ if (!DubboMethodArg.isMatch(dubboMethodArg, parameters[index])) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "DubboMethodMatch{" +
+ "name_match=" + name_match +
+ ", argc=" + argc +
+ ", args=" + args +
+ ", argp=" + argp +
+ ", headers=" + headers +
+ '}';
+ }
+}
+
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListBoolMatch.java
similarity index 61%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListBoolMatch.java
index ff77800..9418bdf 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListBoolMatch.java
@@ -14,24 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
-import java.util.List;
-@SPI
-public interface AddressListener {
-
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
-
-}
\ No newline at end of file
+public class ListBoolMatch {
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatch.java
similarity index 58%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatch.java
index ff77800..c06397d 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatch.java
@@ -14,24 +14,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
import java.util.List;
-@SPI
-public interface AddressListener {
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+public class ListDoubleMatch {
+ private List<DoubleMatch> oneof;
-}
\ No newline at end of file
+ public List<DoubleMatch> getOneof() {
+ return oneof;
+ }
+
+ public void setOneof(List<DoubleMatch> oneof) {
+ this.oneof = oneof;
+ }
+
+ public static boolean isMatch(ListDoubleMatch listDoubleMatch, Double input) {
+
+ for (DoubleMatch doubleMatch : listDoubleMatch.getOneof()) {
+ if (DoubleMatch.isMatch(doubleMatch, input)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatch.java
similarity index 58%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatch.java
index ff77800..e23d623 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatch.java
@@ -14,24 +14,31 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
import java.util.List;
-@SPI
-public interface AddressListener {
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+public class ListStringMatch {
+ private List<StringMatch> oneof;
-}
\ No newline at end of file
+ public List<StringMatch> getOneof() {
+ return oneof;
+ }
+
+ public void setOneof(List<StringMatch> oneof) {
+ this.oneof = oneof;
+ }
+
+
+ public static boolean isMatch(ListStringMatch listStringMatch, String input) {
+
+ for (StringMatch stringMatch : listStringMatch.getOneof()) {
+ if (StringMatch.isMatch(stringMatch, input)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatch.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatch.java
new file mode 100644
index 0000000..555ee5b
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatch.java
@@ -0,0 +1,105 @@
+/*
+ * 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.router.mesh.rule.virtualservice.match;
+
+
+public class StringMatch {
+ private String exact;
+ private String prefix;
+ private String regex;
+ private String noempty;
+ private String empty;
+
+
+ public String getExact() {
+ return exact;
+ }
+
+ public void setExact(String exact) {
+ this.exact = exact;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public String getRegex() {
+ return regex;
+ }
+
+ public void setRegex(String regex) {
+ this.regex = regex;
+ }
+
+ public String getNoempty() {
+ return noempty;
+ }
+
+ public void setNoempty(String noempty) {
+ this.noempty = noempty;
+ }
+
+ public String getEmpty() {
+ return empty;
+ }
+
+ public void setEmpty(String empty) {
+ this.empty = empty;
+ }
+
+
+ public static boolean isMatch(StringMatch stringMatch, String input) {
+ if (stringMatch.getExact() != null && input != null) {
+ if (input.equals(stringMatch.getExact())) {
+ return true;
+ }
+ } else if (stringMatch.getPrefix() != null && input != null) {
+ if (input.startsWith(stringMatch.getPrefix())) {
+ return true;
+ }
+ } else if (stringMatch.getRegex() != null && input != null) {
+ if (input.matches(stringMatch.getRegex())) {
+ return true;
+ }
+ } else if (stringMatch.getEmpty() != null) {
+ return input == null || "".equals(input);
+ } else if (stringMatch.getNoempty() != null) {
+ return input != null && input.length() > 0;
+ } else {
+ return false;
+ }
+
+ return false;
+ }
+
+
+ @Override
+ public String toString() {
+ return "StringMatch{" +
+ "exact='" + exact + '\'' +
+ ", prefix='" + prefix + '\'' +
+ ", regex='" + regex + '\'' +
+ ", noempty='" + noempty + '\'' +
+ ", empty='" + empty + '\'' +
+ '}';
+ }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcher.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcher.java
new file mode 100644
index 0000000..4c1fae2
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcher.java
@@ -0,0 +1,53 @@
+/*
+ * 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.router.mesh.util;
+
+import org.apache.dubbo.common.utils.ConcurrentHashSet;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
+
+import java.util.Set;
+
+
+public class VsDestinationGroupRuleDispatcher {
+
+ private Set<VsDestinationGroupRuleListener> listenerSet = new ConcurrentHashSet<>();
+
+ public synchronized void post(VsDestinationGroup vsDestinationGroup) {
+ for (VsDestinationGroupRuleListener vsDestinationGroupRuleListener : listenerSet) {
+ try {
+ vsDestinationGroupRuleListener.onRuleChange(vsDestinationGroup);
+ } catch (Throwable throwable) {
+
+ }
+ }
+ }
+
+ public synchronized boolean register(VsDestinationGroupRuleListener listener) {
+ if (listener == null) {
+ return false;
+ }
+ return listenerSet.add(listener);
+ }
+
+ public synchronized void unregister(VsDestinationGroupRuleListener listener) {
+ if (listener == null) {
+ return;
+ }
+ listenerSet.remove(listener);
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleListener.java
similarity index 61%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleListener.java
index ff77800..9e830ef 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleListener.java
@@ -14,24 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.util;
-import java.util.List;
-@SPI
-public interface AddressListener {
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
-
-}
\ No newline at end of file
+public interface VsDestinationGroupRuleListener {
+ void onRuleChange(VsDestinationGroup vsDestinationGroup);
+}
diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.AddressListener b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.AddressListener
new file mode 100644
index 0000000..754e5ee
--- /dev/null
+++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.AddressListener
@@ -0,0 +1 @@
+mesh-rule=org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleAddressListenerInterceptor
\ No newline at end of file
diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory
index 2a807f0..1890efc 100644
--- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory
+++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory
@@ -5,3 +5,4 @@ service=org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouterFactor
app=org.apache.dubbo.rpc.cluster.router.condition.config.AppRouterFactory
tag=org.apache.dubbo.rpc.cluster.router.tag.TagRouterFactory
mock=org.apache.dubbo.rpc.cluster.router.mock.MockRouterFactory
+mesh-rule=org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleRouterFactory
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java
new file mode 100644
index 0000000..8b89daa
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java
@@ -0,0 +1,180 @@
+/*
+ * 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.router.mesh.route;
+
+import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
+import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+
+public class MeshAppRuleListenerTest {
+
+ @Test
+ public void receiveConfigInfo() {
+ MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener("qinliujie");
+
+ MeshRuleRouter meshRuleRouter = mock(MeshRuleRouter.class);
+ meshAppRuleListener.register(meshRuleRouter);
+
+ meshAppRuleListener.receiveConfigInfo("apiVersion: service.dubbo.apache.org/v1alpha1\n" +
+ "kind: DestinationRule\n" +
+ "metadata: { name: demo-route }\n" +
+ "spec:\n" +
+ " host: demo\n" +
+ " subsets:\n" +
+ " - labels: { env-sign: xxx, tag1: hello }\n" +
+ " name: isolation\n" +
+ " - labels: { env-sign: yyy }\n" +
+ " name: testing-trunk\n" +
+ " - labels: { env-sign: zzz }\n" +
+ " name: testing\n" +
+ " trafficPolicy:\n" +
+ " loadBalancer: { simple: ROUND_ROBIN }\n" +
+ "\n" +
+ "---\n" +
+ "\n" +
+ "apiVersion: service.dubbo.apache.org/v1alpha1\n" +
+ "kind: VirtualService\n" +
+ "metadata: {name: demo-route}\n" +
+ "spec:\n" +
+ " dubbo:\n" +
+ " - routedetail:\n" +
+ " - match:\n" +
+ " - sourceLabels: {trafficLabel: xxx}\n" +
+ " name: xxx-project\n" +
+ " route:\n" +
+ " - destination: {host: demo, subset: isolation}\n" +
+ " - match:\n" +
+ " - sourceLabels: {trafficLabel: testing-trunk}\n" +
+ " name: testing-trunk\n" +
+ " route:\n" +
+ " - destination: {host: demo, subset: testing-trunk}\n" +
+ " - name: testing\n" +
+ " route:\n" +
+ " - destination: {host: demo, subset: testing}\n" +
+ " services:\n" +
+ " - {regex: ccc}\n" +
+ " hosts: [demo]\n");
+
+
+ ArgumentCaptor<VsDestinationGroup> captor = ArgumentCaptor.forClass(VsDestinationGroup.class);
+ verify(meshRuleRouter, times(1)).onRuleChange(captor.capture());
+
+ VsDestinationGroup vsDestinationGroup = captor.getValue();
+
+ assertTrue(vsDestinationGroup.getAppName().equals("qinliujie"));
+ assertTrue(vsDestinationGroup.getDestinationRuleList().size() == 1);
+ assertTrue(vsDestinationGroup.getVirtualServiceRuleList().size() == 1);
+
+
+ meshAppRuleListener.receiveConfigInfo("");
+ verify(meshRuleRouter, times(2)).onRuleChange(captor.capture());
+
+ VsDestinationGroup vsDestinationGroup1 = captor.getAllValues().get(captor.getAllValues().size() - 1);
+
+ assertTrue(vsDestinationGroup1.getAppName().equals("qinliujie"));
+ assertTrue(vsDestinationGroup1.getDestinationRuleList().size() == 0);
+ assertTrue(vsDestinationGroup1.getVirtualServiceRuleList().size() == 0);
+ }
+
+ @Test
+ public void register() {
+ }
+
+ @Test
+ public void unregister() {
+ }
+
+ @Test
+ public void process() {
+ MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener("qinliujie");
+
+ MeshRuleRouter meshRuleRouter = mock(MeshRuleRouter.class);
+ meshAppRuleListener.register(meshRuleRouter);
+
+ ConfigChangedEvent configChangedEvent = new ConfigChangedEvent("qinliujie", "HSF", "apiVersion: service.dubbo.apache.org/v1alpha1\n" +
+ "kind: DestinationRule\n" +
+ "metadata: { name: demo-route }\n" +
+ "spec:\n" +
+ " host: demo\n" +
+ " subsets:\n" +
+ " - labels: { env-sign: xxx, tag1: hello }\n" +
+ " name: isolation\n" +
+ " - labels: { env-sign: yyy }\n" +
+ " name: testing-trunk\n" +
+ " - labels: { env-sign: zzz }\n" +
+ " name: testing\n" +
+ " trafficPolicy:\n" +
+ " loadBalancer: { simple: ROUND_ROBIN }\n" +
+ "\n" +
+ "---\n" +
+ "\n" +
+ "apiVersion: service.dubbo.apache.org/v1alpha1\n" +
+ "kind: VirtualService\n" +
+ "metadata: {name: demo-route}\n" +
+ "spec:\n" +
+ " dubbo:\n" +
+ " - routedetail:\n" +
+ " - match:\n" +
+ " - sourceLabels: {trafficLabel: xxx}\n" +
+ " name: xxx-project\n" +
+ " route:\n" +
+ " - destination: {host: demo, subset: isolation}\n" +
+ " - match:\n" +
+ " - sourceLabels: {trafficLabel: testing-trunk}\n" +
+ " name: testing-trunk\n" +
+ " route:\n" +
+ " - destination: {host: demo, subset: testing-trunk}\n" +
+ " - name: testing\n" +
+ " route:\n" +
+ " - destination: {host: demo, subset: testing}\n" +
+ " services:\n" +
+ " - {regex: ccc}\n" +
+ " hosts: [demo]\n", ConfigChangeType.MODIFIED);
+
+
+ meshAppRuleListener.process(configChangedEvent);
+
+ ArgumentCaptor<VsDestinationGroup> captor = ArgumentCaptor.forClass(VsDestinationGroup.class);
+ verify(meshRuleRouter, times(1)).onRuleChange(captor.capture());
+
+ VsDestinationGroup vsDestinationGroup = captor.getValue();
+
+ assertTrue(vsDestinationGroup.getAppName().equals("qinliujie"));
+ assertTrue(vsDestinationGroup.getDestinationRuleList().size() == 1);
+ assertTrue(vsDestinationGroup.getVirtualServiceRuleList().size() == 1);
+
+
+ meshAppRuleListener.receiveConfigInfo("");
+ verify(meshRuleRouter, times(2)).onRuleChange(captor.capture());
+
+ VsDestinationGroup vsDestinationGroup1 = captor.getAllValues().get(captor.getAllValues().size() - 1);
+
+ assertTrue(vsDestinationGroup1.getAppName().equals("qinliujie"));
+ assertTrue(vsDestinationGroup1.getDestinationRuleList().size() == 0);
+ assertTrue(vsDestinationGroup1.getVirtualServiceRuleList().size() == 0);
+
+ }
+}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java
new file mode 100644
index 0000000..7638c85
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.router.mesh.route;
+
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+public class MeshRuleManagerTest {
+
+ @Test
+ public void subscribeAppRule() {
+ Optional<DynamicConfiguration> before = ApplicationModel.getEnvironment().getDynamicConfiguration();
+ try {
+ DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
+
+ ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration);
+
+ MeshRuleManager.subscribeAppRule("test");
+
+ ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
+ Mockito.verify(dynamicConfiguration).getConfig(captor.capture(), anyString(), anyLong());
+
+ String result = captor.getValue();
+
+ assertEquals("test.MESHAPPRULE", result);
+ } finally {
+ ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null));
+ }
+
+
+ }
+
+ @Test
+ public void register() {
+ Optional<DynamicConfiguration> before = ApplicationModel.getEnvironment().getDynamicConfiguration();
+ try {
+ DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
+
+ ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration);
+
+ when(dynamicConfiguration.getConfig(anyString(), anyString(), anyLong())).thenReturn("apiVersion: service.dubbo.apache.org/v1alpha1\n" +
+ "kind: VirtualService\n" +
+ "metadata: {name: demo-route}\n" +
+ "spec:\n" +
+ " dubbo:\n" +
+ " - routedetail:\n" +
+ " - match:\n" +
+ " - sourceLabels: {trafficLabel: xxx}\n" +
+ " name: xxx-project\n" +
+ " route:\n" +
+ " - destination: {host: demo, subset: isolation}\n" +
+ " - match:\n" +
+ " - sourceLabels: {trafficLabel: testing-trunk}\n" +
+ " name: testing-trunk\n" +
+ " route:\n" +
+ " - destination: {host: demo, subset: testing-trunk}\n" +
+ " - name: testing\n" +
+ " route:\n" +
+ " - destination: {host: demo, subset: testing}\n" +
+ " services:\n" +
+ " - {regex: ccc}\n" +
+ " hosts: [demo]\n");
+
+ MeshRuleManager.subscribeAppRule("test");
+
+
+ MeshRuleRouter meshRuleRouter = mock(MeshRuleRouter.class);
+
+ MeshRuleManager.register("test", meshRuleRouter);
+
+ ArgumentCaptor<VsDestinationGroup> captor = ArgumentCaptor.forClass(VsDestinationGroup.class);
+
+
+ Mockito.verify(meshRuleRouter).onRuleChange(captor.capture());
+
+ VsDestinationGroup result = captor.getValue();
+
+ assertNotNull(result);
+ assertEquals("test", result.getAppName());
+ assertEquals(1, result.getVirtualServiceRuleList().size());
+ assertEquals(0, result.getDestinationRuleList().size());
+ } finally {
+ ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null));
+ }
+ }
+
+ @Test
+ public void unregister() {
+ Optional<DynamicConfiguration> before = ApplicationModel.getEnvironment().getDynamicConfiguration();
+ try {
+ DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
+
+ ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration);
+
+ when(dynamicConfiguration.getConfig(anyString(), anyString(), anyLong())).thenReturn("apiVersion: service.dubbo.apache.org/v1alpha1\n" +
+ "kind: VirtualService\n" +
+ "metadata: {name: demo-route}\n" +
+ "spec:\n" +
+ " dubbo:\n" +
+ " - routedetail:\n" +
+ " - match:\n" +
+ " - sourceLabels: {trafficLabel: xxx}\n" +
+ " name: xxx-project\n" +
+ " route:\n" +
+ " - destination: {host: demo, subset: isolation}\n" +
+ " - match:\n" +
+ " - sourceLabels: {trafficLabel: testing-trunk}\n" +
+ " name: testing-trunk\n" +
+ " route:\n" +
+ " - destination: {host: demo, subset: testing-trunk}\n" +
+ " - name: testing\n" +
+ " route:\n" +
+ " - destination: {host: demo, subset: testing}\n" +
+ " services:\n" +
+ " - {regex: ccc}\n" +
+ " hosts: [demo]\n");
+
+ MeshRuleManager.subscribeAppRule("test");
+
+
+ MeshRuleRouter meshRuleRouter = mock(MeshRuleRouter.class);
+
+ MeshRuleManager.register("test", meshRuleRouter);
+
+ MeshRuleManager.unregister(meshRuleRouter);
+
+ } finally {
+ ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null));
+ }
+ }
+}
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java
similarity index 63%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java
index ff77800..7bdc47a 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java
@@ -14,24 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
+
+package org.apache.dubbo.rpc.cluster.router.mesh.route;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+import org.junit.jupiter.api.Test;
-import java.util.List;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
-@SPI
-public interface AddressListener {
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+public class MeshRuleRouterFactoryTest {
+ @Test
+ public void getRouter() {
+ MeshRuleRouterFactory ruleRouterFactory = new MeshRuleRouterFactory();
+ URL url = mock(URL.class);
+ when(url.getServiceKey()).thenReturn("demoService");
+ ruleRouterFactory.getRouter(url);
+ }
}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterTest.java
new file mode 100644
index 0000000..8262cd6
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterTest.java
@@ -0,0 +1,1407 @@
+/*
+ * 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.router.mesh.route;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRule;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRuleSpec;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.Subset;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.DubboMatchRequest;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.DubboRoute;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.DubboRouteDetail;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceRule;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceSpec;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination.DubboDestination;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination.DubboRouteDestination;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.DubboMethodMatch;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+public class MeshRuleRouterTest {
+
+ @Test
+ public void containMapKeyValue() {
+ URL url = mock(URL.class);
+ when(url.getServiceKey()).thenReturn("test");
+ MeshRuleRouter meshRuleRouter = new MeshRuleRouter(url);
+
+ Map<String, String> originMap = new HashMap<>();
+
+ originMap.put("key1", "value1");
+ originMap.put("key2", "value2");
+ originMap.put("key3", "value3");
+
+ Map<String, String> inputMap = new HashMap<>();
+
+ inputMap.put("key1", "value1");
+ inputMap.put("key2", "value2");
+
+ assertTrue(meshRuleRouter.containMapKeyValue(originMap, inputMap));
+
+ inputMap.put("key4", "value4");
+ assertFalse(meshRuleRouter.containMapKeyValue(originMap, inputMap));
+
+
+ assertTrue(meshRuleRouter.containMapKeyValue(originMap, null));
+ assertTrue(meshRuleRouter.containMapKeyValue(originMap, new HashMap<>()));
+
+ }
+
+ @Test
+ public void computeSubsetMap() {
+ URL url = mock(URL.class);
+ when(url.getServiceKey()).thenReturn("test");
+ MeshRuleRouter meshRuleRouter = new MeshRuleRouter(url);
+
+ List<Invoker<?>> invokers = new ArrayList<>();
+
+ //--
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test1");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test2");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test3");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+
+ //--
+
+ List<DestinationRule> destinationRules = new ArrayList<>();
+
+ //--
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test1");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test1");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test2");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test2");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test4");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test4");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+
+ //--
+
+
+ Map<String, List<Invoker<?>>> result = meshRuleRouter.computeSubsetMap(invokers, destinationRules);
+
+ assertTrue(result.size() == 3);
+ assertTrue(result.containsKey("test1"));
+ assertTrue(result.containsKey("test2"));
+ assertTrue(result.containsKey("test4"));
+
+ assertTrue(result.get("test1").size() == 1);
+ assertTrue(result.get("test2").size() == 1);
+ assertTrue(result.get("test4").size() == 0);
+
+ }
+
+ @Test
+ public void computeSubset() {
+
+ URL url = mock(URL.class);
+ when(url.getServiceKey()).thenReturn("test");
+ MeshRuleRouter meshRuleRouter = new MeshRuleRouter(url);
+
+
+ meshRuleRouter.setInvokerList(null);
+ meshRuleRouter.computeSubset();
+
+ assertNull(meshRuleRouter.getSubsetMap());
+
+ List<Invoker<?>> invokers = new ArrayList<>();
+
+ //--
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test1");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test2");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test3");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+
+ meshRuleRouter.setInvokerList(invokers);
+
+ meshRuleRouter.computeSubset();
+
+ assertNull(meshRuleRouter.getSubsetMap());
+
+
+ VsDestinationGroup vsDestinationGroup = new VsDestinationGroup();
+
+ List<DestinationRule> destinationRules = new ArrayList<>();
+
+ //--
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test1");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test1");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test2");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test2");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test4");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test4");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+
+ vsDestinationGroup.setDestinationRuleList(destinationRules);
+
+ meshRuleRouter.setVsDestinationGroup(vsDestinationGroup);
+
+
+ meshRuleRouter.computeSubset();
+
+ assertNotNull(meshRuleRouter.getSubsetMap());
+ assertTrue(meshRuleRouter.getSubsetMap().size() == 3);
+ }
+
+ @Test
+ public void findMatchDubboRouteDetail() {
+
+ URL url = mock(URL.class);
+ when(url.getServiceKey()).thenReturn("test");
+ MeshRuleRouter meshRuleRouter = new MeshRuleRouter(url);
+
+ Invocation invocation = mock(Invocation.class);
+ when(invocation.getMethodName()).thenReturn("sayHello");
+ when(invocation.getArguments()).thenReturn(new Object[]{"qinliujie"});
+ when(invocation.getCompatibleParamSignatures()).thenReturn(new String[]{String.class.getName()});
+
+ assertNull(meshRuleRouter.findMatchDubboRouteDetail(new ArrayList<>(), invocation));
+
+ //--
+ {
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHello");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+
+ DubboRouteDetail result = meshRuleRouter.findMatchDubboRouteDetail(dubboRouteDetailList, invocation);
+ assertNotNull(result);
+ assertEquals("test", result.getName());
+ }
+
+ {
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHi");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+
+ DubboRouteDetail result = meshRuleRouter.findMatchDubboRouteDetail(dubboRouteDetailList, invocation);
+ assertNull(result);
+ }
+
+
+ {
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ {
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHi");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+ }
+
+
+ {
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test2");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHello");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+ }
+
+ DubboRouteDetail result = meshRuleRouter.findMatchDubboRouteDetail(dubboRouteDetailList, invocation);
+ assertNotNull(result);
+ assertEquals("test2", result.getName());
+ }
+
+ }
+
+ @Test
+ public void getDubboRouteDestination() {
+ URL url = mock(URL.class);
+ when(url.getServiceKey()).thenReturn("test");
+ MeshRuleRouter meshRuleRouter = new MeshRuleRouter(url);
+
+ Invocation invocation = mock(Invocation.class);
+ when(invocation.getMethodName()).thenReturn("sayHello");
+ when(invocation.getArguments()).thenReturn(new Object[]{"qinliujie"});
+ when(invocation.getCompatibleParamSignatures()).thenReturn(new String[]{String.class.getName()});
+
+ DubboRoute dubboRoute = new DubboRoute();
+
+ {
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHi");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ List<DubboRouteDestination> dubboRouteDestinations = new ArrayList<>();
+ dubboRouteDestinations.add(new DubboRouteDestination());
+ dubboRouteDetail.setRoute(dubboRouteDestinations);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+ dubboRoute.setRoutedetail(dubboRouteDetailList);
+ assertNull(meshRuleRouter.getDubboRouteDestination(dubboRoute, invocation));
+ }
+
+
+ {
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHello");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ List<DubboRouteDestination> dubboRouteDestinations = new ArrayList<>();
+ dubboRouteDestinations.add(new DubboRouteDestination());
+ dubboRouteDetail.setRoute(dubboRouteDestinations);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+ dubboRoute.setRoutedetail(dubboRouteDetailList);
+ assertNotNull(meshRuleRouter.getDubboRouteDestination(dubboRoute, invocation));
+ }
+ }
+
+ @Test
+ public void getDubboRoute() {
+
+ URL url = mock(URL.class);
+ when(url.getServiceKey()).thenReturn("test");
+ MeshRuleRouter meshRuleRouter = new MeshRuleRouter(url);
+
+ Invocation invocation = mock(Invocation.class);
+ when(invocation.getMethodName()).thenReturn("sayHello");
+ when(invocation.getArguments()).thenReturn(new Object[]{"qinliujie"});
+ when(invocation.getCompatibleParamSignatures()).thenReturn(new String[]{String.class.getName()});
+ when(invocation.getServiceName()).thenReturn("demoService");
+
+ DubboRoute dubboRoute = new DubboRoute();
+
+ {
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHello");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ List<DubboRouteDestination> dubboRouteDestinations = new ArrayList<>();
+ dubboRouteDestinations.add(new DubboRouteDestination());
+ dubboRouteDetail.setRoute(dubboRouteDestinations);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+ dubboRoute.setRoutedetail(dubboRouteDetailList);
+
+
+ dubboRoute.setServices(new ArrayList<>());
+
+ VirtualServiceRule virtualServiceRule = new VirtualServiceRule();
+ //virtualServiceRule.
+
+
+ VirtualServiceSpec spec = new VirtualServiceSpec();
+ List<DubboRoute> dubbo = new ArrayList<>();
+ dubbo.add(dubboRoute);
+
+ spec.setDubbo(dubbo);
+
+ virtualServiceRule.setSpec(spec);
+ DubboRoute result = meshRuleRouter.getDubboRoute(virtualServiceRule, invocation);
+
+ assertNotNull(result);
+ }
+
+
+ {
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHello");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ List<DubboRouteDestination> dubboRouteDestinations = new ArrayList<>();
+ dubboRouteDestinations.add(new DubboRouteDestination());
+ dubboRouteDetail.setRoute(dubboRouteDestinations);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+ dubboRoute.setRoutedetail(dubboRouteDetailList);
+ List<StringMatch> serviceMatchList = new ArrayList<>();
+ StringMatch serviceNameMatch = new StringMatch();
+ serviceNameMatch.setExact("otherService");
+
+ serviceMatchList.add(serviceNameMatch);
+
+ dubboRoute.setServices(serviceMatchList);
+
+ VirtualServiceRule virtualServiceRule = new VirtualServiceRule();
+ //virtualServiceRule.
+
+
+ VirtualServiceSpec spec = new VirtualServiceSpec();
+ List<DubboRoute> dubbo = new ArrayList<>();
+ dubbo.add(dubboRoute);
+
+ spec.setDubbo(dubbo);
+ virtualServiceRule.setSpec(spec);
+
+ DubboRoute result = meshRuleRouter.getDubboRoute(virtualServiceRule, invocation);
+
+ assertNull(result);
+ }
+
+
+ {
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHello");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ List<DubboRouteDestination> dubboRouteDestinations = new ArrayList<>();
+ dubboRouteDestinations.add(new DubboRouteDestination());
+ dubboRouteDetail.setRoute(dubboRouteDestinations);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+ dubboRoute.setRoutedetail(dubboRouteDetailList);
+ List<StringMatch> serviceMatchList = new ArrayList<>();
+ StringMatch serviceNameMatch = new StringMatch();
+ serviceNameMatch.setRegex(".*");
+
+ serviceMatchList.add(serviceNameMatch);
+
+ dubboRoute.setServices(serviceMatchList);
+
+ VirtualServiceRule virtualServiceRule = new VirtualServiceRule();
+ //virtualServiceRule.
+
+
+ VirtualServiceSpec spec = new VirtualServiceSpec();
+ List<DubboRoute> dubbo = new ArrayList<>();
+ dubbo.add(dubboRoute);
+
+ spec.setDubbo(dubbo);
+ virtualServiceRule.setSpec(spec);
+ DubboRoute result = meshRuleRouter.getDubboRoute(virtualServiceRule, invocation);
+
+ assertNotNull(result);
+ }
+
+ {
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHi");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ List<DubboRouteDestination> dubboRouteDestinations = new ArrayList<>();
+ dubboRouteDestinations.add(new DubboRouteDestination());
+ dubboRouteDetail.setRoute(dubboRouteDestinations);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+ dubboRoute.setRoutedetail(dubboRouteDetailList);
+ List<StringMatch> serviceMatchList = new ArrayList<>();
+ StringMatch serviceNameMatch = new StringMatch();
+ serviceNameMatch.setRegex(".*");
+
+ serviceMatchList.add(serviceNameMatch);
+
+ dubboRoute.setServices(serviceMatchList);
+
+ VirtualServiceRule virtualServiceRule = new VirtualServiceRule();
+ //virtualServiceRule.
+
+
+ VirtualServiceSpec spec = new VirtualServiceSpec();
+ List<DubboRoute> dubbo = new ArrayList<>();
+ dubbo.add(dubboRoute);
+
+ spec.setDubbo(dubbo);
+ virtualServiceRule.setSpec(spec);
+ DubboRoute result = meshRuleRouter.getDubboRoute(virtualServiceRule, invocation);
+
+ assertNotNull(result);
+ }
+
+
+ }
+
+ @Test
+ public void testNotify() {
+
+ URL url = mock(URL.class);
+ when(url.getServiceKey()).thenReturn("test");
+ MeshRuleRouter meshRuleRouter = new MeshRuleRouter(url);
+
+
+ meshRuleRouter.setInvokerList(null);
+ meshRuleRouter.computeSubset();
+
+ assertNull(meshRuleRouter.getSubsetMap());
+
+ List<Invoker<?>> invokers = new ArrayList<>();
+
+ //--
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test1");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test2");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test3");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+ VsDestinationGroup vsDestinationGroup = new VsDestinationGroup();
+
+ List<DestinationRule> destinationRules = new ArrayList<>();
+
+ //--
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test1");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test1");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test2");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test2");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test4");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test4");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+
+ vsDestinationGroup.setDestinationRuleList(destinationRules);
+
+ meshRuleRouter.setVsDestinationGroup(vsDestinationGroup);
+
+ meshRuleRouter.notify((List) invokers);
+
+ assertNotNull(meshRuleRouter.getSubsetMap());
+
+ }
+
+ @Test
+ public void route() {
+ URL url = mock(URL.class);
+ when(url.getServiceKey()).thenReturn("test");
+ MeshRuleRouter meshRuleRouter = new MeshRuleRouter(url);
+
+ List<Invoker<?>> inputInvokers = new ArrayList<>();
+
+ URL inputURL = mock(URL.class);
+
+ Invocation invocation = mock(Invocation.class);
+ when(invocation.getMethodName()).thenReturn("sayHello");
+ when(invocation.getArguments()).thenReturn(new Object[]{"qinliujie"});
+ when(invocation.getCompatibleParamSignatures()).thenReturn(new String[]{String.class.getName()});
+ when(invocation.getServiceName()).thenReturn("demoService");
+
+
+ List<Invoker<?>> invokers = new ArrayList<>();
+
+ //--
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test1");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test2");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test3");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+
+ meshRuleRouter.setInvokerList(invokers);
+
+
+ VsDestinationGroup vsDestinationGroup = new VsDestinationGroup();
+
+ List<DestinationRule> destinationRules = new ArrayList<>();
+
+ //--
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test1");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test1");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test2");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test2");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+ vsDestinationGroup.setDestinationRuleList(destinationRules);
+
+ meshRuleRouter.setVsDestinationGroup(vsDestinationGroup);
+
+
+ {
+ DubboRoute dubboRoute = new DubboRoute();
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHello");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ List<DubboRouteDestination> dubboRouteDestinations = new ArrayList<>();
+ dubboRouteDestinations.add(new DubboRouteDestination());
+ dubboRouteDetail.setRoute(dubboRouteDestinations);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+ dubboRoute.setRoutedetail(dubboRouteDetailList);
+ List<StringMatch> serviceMatchList = new ArrayList<>();
+ StringMatch serviceNameMatch = new StringMatch();
+ serviceNameMatch.setExact("otherService");
+
+ serviceMatchList.add(serviceNameMatch);
+
+ dubboRoute.setServices(serviceMatchList);
+
+ VirtualServiceRule virtualServiceRule = new VirtualServiceRule();
+ //virtualServiceRule.
+
+
+ VirtualServiceSpec spec = new VirtualServiceSpec();
+ List<DubboRoute> dubbo = new ArrayList<>();
+ dubbo.add(dubboRoute);
+
+ spec.setDubbo(dubbo);
+ virtualServiceRule.setSpec(spec);
+
+ List<VirtualServiceRule> virtualServiceRuleList = new ArrayList<>();
+ virtualServiceRuleList.add(virtualServiceRule);
+ vsDestinationGroup.setVirtualServiceRuleList(virtualServiceRuleList);
+ meshRuleRouter.computeSubset();
+ assertEquals(inputInvokers, meshRuleRouter.route((List) inputInvokers, inputURL, invocation));
+ }
+
+
+ {
+ DubboRoute dubboRoute = new DubboRoute();
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHello");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ List<DubboRouteDestination> dubboRouteDestinations = new ArrayList<>();
+ DubboRouteDestination dubboRouteDestination = new DubboRouteDestination();
+ DubboDestination destination = new DubboDestination();
+ destination.setSubset("test1");
+ dubboRouteDestination.setDestination(destination);
+ dubboRouteDestinations.add(dubboRouteDestination);
+
+
+ dubboRouteDetail.setRoute(dubboRouteDestinations);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+ dubboRoute.setRoutedetail(dubboRouteDetailList);
+ List<StringMatch> serviceMatchList = new ArrayList<>();
+ StringMatch serviceNameMatch = new StringMatch();
+ serviceNameMatch.setRegex(".*");
+
+ serviceMatchList.add(serviceNameMatch);
+
+ dubboRoute.setServices(serviceMatchList);
+
+ VirtualServiceRule virtualServiceRule = new VirtualServiceRule();
+ //virtualServiceRule.
+
+
+ VirtualServiceSpec spec = new VirtualServiceSpec();
+ List<DubboRoute> dubbo = new ArrayList<>();
+ dubbo.add(dubboRoute);
+
+ spec.setDubbo(dubbo);
+ virtualServiceRule.setSpec(spec);
+
+ List<VirtualServiceRule> virtualServiceRuleList = new ArrayList<>();
+ virtualServiceRuleList.add(virtualServiceRule);
+ vsDestinationGroup.setVirtualServiceRuleList(virtualServiceRuleList);
+ meshRuleRouter.computeSubset();
+ assertNotEquals(inputInvokers, meshRuleRouter.route((List) inputInvokers, inputURL, invocation));
+ assertEquals(1, meshRuleRouter.route((List) inputInvokers, inputURL, invocation).size());
+
+ Map<String, String> invokerParameterMap = new HashMap<>();
+ invokerParameterMap.put("env", "test1");
+
+ assertEquals(invokerParameterMap, ((Invoker) meshRuleRouter.route((List) inputInvokers, inputURL, invocation).get(0)).getUrl().getParameters());
+ }
+ }
+
+
+ @Test
+ public void routeFallback() {
+ URL url = mock(URL.class);
+ when(url.getServiceKey()).thenReturn("test");
+ MeshRuleRouter meshRuleRouter = new MeshRuleRouter(url);
+
+ List<Invoker<?>> inputInvokers = new ArrayList<>();
+
+ URL inputURL = mock(URL.class);
+
+ Invocation invocation = mock(Invocation.class);
+ when(invocation.getMethodName()).thenReturn("sayHello");
+ when(invocation.getArguments()).thenReturn(new Object[]{"qinliujie"});
+ when(invocation.getCompatibleParamSignatures()).thenReturn(new String[]{String.class.getName()});
+ when(invocation.getServiceName()).thenReturn("demoService");
+
+
+ List<Invoker<?>> invokers = new ArrayList<>();
+
+ //--
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test1");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test2");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+
+ {
+ Invoker<?> invoker1 = mock(Invoker.class);
+ URL invoker1URL = mock(URL.class);
+ Map<String, String> invoker1Map = new HashMap<>();
+ invoker1Map.put("env", "test3");
+
+ when(invoker1URL.getParameters()).thenReturn(invoker1Map);
+ when(invoker1.getUrl()).thenReturn(invoker1URL);
+
+ invokers.add(invoker1);
+ }
+
+
+ meshRuleRouter.setInvokerList(invokers);
+
+
+ VsDestinationGroup vsDestinationGroup = new VsDestinationGroup();
+
+ List<DestinationRule> destinationRules = new ArrayList<>();
+
+ //--
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test1");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test1");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+ {
+ DestinationRule destinationRule1 = new DestinationRule();
+
+ DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
+ destinationRuleSpec.setHost("test1");
+
+ List<Subset> subsetList = new ArrayList<>();
+
+ Subset subset = new Subset();
+ subset.setName("test2");
+
+ Map<String, String> subsetTest1Lables = new HashMap<>();
+ subsetTest1Lables.put("env", "test2");
+ subset.setLabels(subsetTest1Lables);
+
+ subsetList.add(subset);
+
+ destinationRuleSpec.setSubsets(subsetList);
+
+ destinationRule1.setSpec(destinationRuleSpec);
+ destinationRules.add(destinationRule1);
+ }
+
+ vsDestinationGroup.setDestinationRuleList(destinationRules);
+
+ meshRuleRouter.setVsDestinationGroup(vsDestinationGroup);
+
+
+ {
+ DubboRoute dubboRoute = new DubboRoute();
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHello");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ List<DubboRouteDestination> dubboRouteDestinations = new ArrayList<>();
+ DubboRouteDestination dubboRouteDestination = new DubboRouteDestination();
+ DubboDestination destination = new DubboDestination();
+ destination.setSubset("test5");
+
+
+ DubboRouteDestination fallbackDubboRouteDestination = new DubboRouteDestination();
+ DubboDestination fallbackDestination = new DubboDestination();
+ fallbackDestination.setSubset("test1");
+ fallbackDubboRouteDestination.setDestination(fallbackDestination);
+
+
+ destination.setFallback(fallbackDubboRouteDestination);
+
+
+ dubboRouteDestination.setDestination(destination);
+ dubboRouteDestinations.add(dubboRouteDestination);
+
+
+ dubboRouteDetail.setRoute(dubboRouteDestinations);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+ dubboRoute.setRoutedetail(dubboRouteDetailList);
+ List<StringMatch> serviceMatchList = new ArrayList<>();
+ StringMatch serviceNameMatch = new StringMatch();
+ serviceNameMatch.setRegex(".*");
+
+ serviceMatchList.add(serviceNameMatch);
+
+ dubboRoute.setServices(serviceMatchList);
+
+ VirtualServiceRule virtualServiceRule = new VirtualServiceRule();
+ //virtualServiceRule.
+
+
+ VirtualServiceSpec spec = new VirtualServiceSpec();
+ List<DubboRoute> dubbo = new ArrayList<>();
+ dubbo.add(dubboRoute);
+
+ spec.setDubbo(dubbo);
+ virtualServiceRule.setSpec(spec);
+
+ List<VirtualServiceRule> virtualServiceRuleList = new ArrayList<>();
+ virtualServiceRuleList.add(virtualServiceRule);
+ vsDestinationGroup.setVirtualServiceRuleList(virtualServiceRuleList);
+ meshRuleRouter.computeSubset();
+ assertNotEquals(inputInvokers, meshRuleRouter.route((List) inputInvokers, inputURL, invocation));
+ assertEquals(1, meshRuleRouter.route((List) inputInvokers, inputURL, invocation).size());
+
+ Map<String, String> invokerParameterMap = new HashMap<>();
+ invokerParameterMap.put("env", "test1");
+
+ assertEquals(invokerParameterMap, ((Invoker) meshRuleRouter.route((List) inputInvokers, inputURL, invocation).get(0)).getUrl().getParameters());
+ }
+
+ {
+ DubboRoute dubboRoute = new DubboRoute();
+ List<DubboRouteDetail> dubboRouteDetailList = new ArrayList<>();
+ DubboRouteDetail dubboRouteDetail = new DubboRouteDetail();
+ dubboRouteDetail.setName("test");
+
+ List<DubboMatchRequest> match = new ArrayList<>();
+
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("sayHello");
+ dubboMethodMatch.setName_match(stringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+
+ match.add(dubboMatchRequest);
+
+ dubboRouteDetail.setMatch(match);
+
+ List<DubboRouteDestination> dubboRouteDestinations = new ArrayList<>();
+ DubboRouteDestination dubboRouteDestination = new DubboRouteDestination();
+ DubboDestination destination = new DubboDestination();
+ destination.setSubset("test5");
+
+
+ DubboRouteDestination fallbackDubboRouteDestination = new DubboRouteDestination();
+ DubboDestination fallbackDestination = new DubboDestination();
+ fallbackDestination.setSubset("test11");
+ fallbackDubboRouteDestination.setDestination(fallbackDestination);
+
+
+ destination.setFallback(fallbackDubboRouteDestination);
+
+
+ dubboRouteDestination.setDestination(destination);
+ dubboRouteDestinations.add(dubboRouteDestination);
+
+
+ dubboRouteDetail.setRoute(dubboRouteDestinations);
+
+ dubboRouteDetailList.add(dubboRouteDetail);
+ dubboRoute.setRoutedetail(dubboRouteDetailList);
+ List<StringMatch> serviceMatchList = new ArrayList<>();
+ StringMatch serviceNameMatch = new StringMatch();
+ serviceNameMatch.setRegex(".*");
+
+ serviceMatchList.add(serviceNameMatch);
+
+ dubboRoute.setServices(serviceMatchList);
+
+ VirtualServiceRule virtualServiceRule = new VirtualServiceRule();
+ //virtualServiceRule.
+
+
+ VirtualServiceSpec spec = new VirtualServiceSpec();
+ List<DubboRoute> dubbo = new ArrayList<>();
+ dubbo.add(dubboRoute);
+
+ spec.setDubbo(dubbo);
+ virtualServiceRule.setSpec(spec);
+
+ List<VirtualServiceRule> virtualServiceRuleList = new ArrayList<>();
+ virtualServiceRuleList.add(virtualServiceRule);
+ vsDestinationGroup.setVirtualServiceRuleList(virtualServiceRuleList);
+ meshRuleRouter.computeSubset();
+
+ assertNull(meshRuleRouter.route((List) inputInvokers, inputURL, invocation));
+
+ meshRuleRouter.setSubsetMap(null);
+ assertNotNull(meshRuleRouter.route((List) inputInvokers, inputURL, invocation));
+ }
+ }
+}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/DestinationRuleTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/DestinationRuleTest.java
new file mode 100644
index 0000000..91f5ac7
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/DestinationRuleTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.router.mesh.rule;
+
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRule;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance.SimpleLB;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceRule;
+import org.junit.jupiter.api.Test;
+import org.yaml.snakeyaml.Yaml;
+
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+
+public class DestinationRuleTest {
+
+ @Test
+ public void parserTest() {
+ Yaml yaml = new Yaml();
+ DestinationRule destinationRule = yaml.loadAs(this.getClass().getClassLoader().getResourceAsStream("DestinationRuleTest.yaml"), DestinationRule.class);
+
+ System.out.println(destinationRule);
+
+
+// apiVersion: service.dubbo.apache.org/v1alpha1
+// kind: DestinationRule
+// metadata: { name: demo-route }
+// spec:
+// host: demo
+// subsets:
+// - labels: { env-sign: xxx,tag1: hello }
+// name: isolation
+// - labels: { env-sign: yyy }
+// name: testing-trunk
+// - labels: { env-sign: zzz }
+// name: testing
+
+
+ assertEquals("service.dubbo.apache.org/v1alpha1", destinationRule.getApiVersion());
+ assertEquals("DestinationRule", destinationRule.getKind());
+ assertEquals("demo-route", destinationRule.getMetadata().get("name"));
+ assertEquals("demo", destinationRule.getSpec().getHost());
+ assertEquals(3, destinationRule.getSpec().getSubsets().size());
+
+ assertEquals("isolation", destinationRule.getSpec().getSubsets().get(0).getName());
+ assertEquals(2, destinationRule.getSpec().getSubsets().get(0).getLabels().size());
+ assertEquals("xxx", destinationRule.getSpec().getSubsets().get(0).getLabels().get("env-sign"));
+ assertEquals("hello", destinationRule.getSpec().getSubsets().get(0).getLabels().get("tag1"));
+
+
+ assertEquals("testing-trunk", destinationRule.getSpec().getSubsets().get(1).getName());
+ assertEquals(1, destinationRule.getSpec().getSubsets().get(1).getLabels().size());
+ assertEquals("yyy", destinationRule.getSpec().getSubsets().get(1).getLabels().get("env-sign"));
+
+
+ assertEquals("testing", destinationRule.getSpec().getSubsets().get(2).getName());
+ assertEquals(1, destinationRule.getSpec().getSubsets().get(2).getLabels().size());
+ assertEquals("zzz", destinationRule.getSpec().getSubsets().get(2).getLabels().get("env-sign"));
+
+ assertEquals(SimpleLB.ROUND_ROBIN, destinationRule.getSpec().getTrafficPolicy().getLoadBalancer().getSimple());
+ assertEquals(null, destinationRule.getSpec().getTrafficPolicy().getLoadBalancer().getConsistentHash());
+ }
+
+
+ @Test
+ public void parserMultiRuleTest() {
+ Yaml yaml = new Yaml();
+ Yaml yaml2 = new Yaml();
+ Iterable objectIterable = yaml.loadAll(this.getClass().getClassLoader().getResourceAsStream("DestinationRuleTest2.yaml"));
+ for (Object result : objectIterable) {
+
+ Map resultMap = (Map) result;
+ if (resultMap.get("kind").equals("DestinationRule")) {
+ DestinationRule destinationRule = yaml2.loadAs(yaml2.dump(result), DestinationRule.class);
+ System.out.println(destinationRule);
+ assertNotNull(destinationRule);
+ } else if (resultMap.get("kind").equals("VirtualService")) {
+ VirtualServiceRule virtualServiceRule = yaml2.loadAs(yaml2.dump(result), VirtualServiceRule.class);
+ System.out.println(virtualServiceRule);
+ assertNotNull(virtualServiceRule);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java
similarity index 55%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
copy to dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java
index ff77800..ddfb127 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java
@@ -14,24 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule;
-import java.util.List;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceRule;
+import org.junit.jupiter.api.Test;
+import org.yaml.snakeyaml.Yaml;
-@SPI
-public interface AddressListener {
+import static org.junit.jupiter.api.Assertions.assertNotNull;
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+
+public class VirtualServiceRuleTest {
+
+ @Test
+ public void parserTest() {
+ Yaml yaml = new Yaml();
+ VirtualServiceRule virtualServiceRule = yaml.loadAs(this.getClass().getClassLoader().getResourceAsStream("VirtualServiceTest.yaml"), VirtualServiceRule.class);
+
+ System.out.println(virtualServiceRule);
+ assertNotNull(virtualServiceRule);
+ }
}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java
new file mode 100644
index 0000000..9bb55b4
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.router.mesh.rule.virtualservice;
+
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.DubboAttachmentMatch;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.DubboMethodMatch;
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+
+public class DubboMatchRequestTest {
+
+ @Test
+ public void isMatch() {
+ DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
+
+ // methodMatch
+ {
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ StringMatch nameStringMatch = new StringMatch();
+ nameStringMatch.setExact("sayHello");
+ dubboMethodMatch.setName_match(nameStringMatch);
+
+ dubboMatchRequest.setMethod(dubboMethodMatch);
+ }
+ assertTrue(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, new HashMap(), new HashMap(), new HashMap(), new HashMap()));
+ assertFalse(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHi", new String[]{}, new Object[]{}, new HashMap(), new HashMap(), new HashMap(), new HashMap()));
+ // sourceLabels
+ {
+ Map<String, String> sourceLabels = new HashMap<>();
+ sourceLabels.put("key1", "value1");
+ sourceLabels.put("key2", "value2");
+
+ dubboMatchRequest.setSourceLabels(sourceLabels);
+ }
+
+ Map<String, String> inputSourceLablesMap = new HashMap<>();
+ inputSourceLablesMap.put("key1", "value1");
+ inputSourceLablesMap.put("key2", "value2");
+ inputSourceLablesMap.put("key3", "value3");
+
+ Map<String, String> inputSourceLablesMap2 = new HashMap<>();
+ inputSourceLablesMap2.put("key1", "other");
+ inputSourceLablesMap2.put("key2", "value2");
+ inputSourceLablesMap2.put("key3", "value3");
+
+ assertTrue(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, new HashMap(), new HashMap(), new HashMap()));
+ assertFalse(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap2, new HashMap(), new HashMap(), new HashMap()));
+
+
+ // eagleeyeContext
+ {
+ DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
+
+ {
+ Map<String, StringMatch> eagleeyecontextMatchMap = new HashMap<>();
+ StringMatch nameMatch = new StringMatch();
+ nameMatch.setExact("qinliujie");
+ eagleeyecontextMatchMap.put("name", nameMatch);
+ dubboAttachmentMatch.setEagleeyecontext(eagleeyecontextMatchMap);
+ }
+
+ dubboMatchRequest.setAttachments(dubboAttachmentMatch);
+ }
+
+ Map<String, String> invokeEagleEyeContextMap = new HashMap<>();
+ invokeEagleEyeContextMap.put("name", "qinliujie");
+ invokeEagleEyeContextMap.put("machineGroup", "test_host");
+ invokeEagleEyeContextMap.put("other", "other");
+
+ assertTrue(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, invokeEagleEyeContextMap, new HashMap(), new HashMap()));
+
+
+ Map<String, String> invokeEagleEyeContextMap2 = new HashMap<>();
+ invokeEagleEyeContextMap2.put("name", "jack");
+ invokeEagleEyeContextMap2.put("machineGroup", "test_host");
+ invokeEagleEyeContextMap2.put("other", "other");
+
+ assertFalse(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, invokeEagleEyeContextMap2, new HashMap(), new HashMap()));
+
+
+ //dubbo context
+
+ {
+ DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
+
+ {
+ Map<String, StringMatch> eagleeyecontextMatchMap = new HashMap<>();
+ StringMatch nameMatch = new StringMatch();
+ nameMatch.setExact("qinliujie");
+ eagleeyecontextMatchMap.put("name", nameMatch);
+ dubboAttachmentMatch.setEagleeyecontext(eagleeyecontextMatchMap);
+ }
+
+
+ {
+ Map<String, StringMatch> dubboContextMatchMap = new HashMap<>();
+ StringMatch dpathMatch = new StringMatch();
+ dpathMatch.setExact("PRE");
+ dubboContextMatchMap.put("dpath", dpathMatch);
+ dubboAttachmentMatch.setDubbocontext(dubboContextMatchMap);
+ }
+
+ dubboMatchRequest.setAttachments(dubboAttachmentMatch);
+ }
+
+
+ Map<String, String> invokeDubboContextMap = new HashMap<>();
+ invokeDubboContextMap.put("dpath", "PRE");
+
+ assertTrue(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, invokeEagleEyeContextMap, invokeDubboContextMap, new HashMap()));
+
+
+ Map<String, String> invokeDubboContextMap2 = new HashMap<>();
+ invokeDubboContextMap.put("dpath", "other");
+
+ assertFalse(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, invokeEagleEyeContextMap, invokeDubboContextMap2, new HashMap()));
+ }
+}
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java
similarity index 55%
rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
rename to dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java
index ff77800..72d4774 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java
@@ -14,24 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.cluster.Directory;
+package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
-import java.util.List;
-@SPI
-public interface AddressListener {
+import org.junit.jupiter.api.Test;
- /**
- * processing when receiving the address list
- *
- * @param addresses provider address list
- * @param consumerUrl
- * @param registryDirectory
- */
- List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+public class BoolMatchTest {
+
+ @Test
+ public void isMatch() {
+ BoolMatch boolMatch = new BoolMatch();
+ boolMatch.setExact(true);
+
+
+ assertTrue(BoolMatch.isMatch(boolMatch,true));
+ assertFalse(BoolMatch.isMatch(boolMatch,false));
+
+ boolMatch.setExact(false);
+ assertFalse(BoolMatch.isMatch(boolMatch,true));
+ assertTrue(BoolMatch.isMatch(boolMatch,false));
+
+ }
}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatchTest.java
new file mode 100644
index 0000000..aba44bc
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatchTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.router.mesh.rule.virtualservice.match;
+
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class DoubleMatchTest {
+
+ @Test
+ public void exactMatch() {
+ DoubleMatch doubleMatch = new DoubleMatch();
+ doubleMatch.setExact(10.0);
+
+ assertTrue(DoubleMatch.isMatch(doubleMatch, 10.0));
+ assertFalse(DoubleMatch.isMatch(doubleMatch, 9.0));
+ }
+
+ @Test
+ public void rangeStartMatch() {
+ DoubleMatch doubleMatch = new DoubleMatch();
+
+ DoubleRangeMatch doubleRangeMatch = new DoubleRangeMatch();
+ doubleRangeMatch.setStart(10.0);
+
+ doubleMatch.setRange(doubleRangeMatch);
+
+ assertTrue(DoubleMatch.isMatch(doubleMatch, 10.0));
+ assertFalse(DoubleMatch.isMatch(doubleMatch, 9.0));
+ }
+
+
+ @Test
+ public void rangeEndMatch() {
+ DoubleMatch doubleMatch = new DoubleMatch();
+
+ DoubleRangeMatch doubleRangeMatch = new DoubleRangeMatch();
+ doubleRangeMatch.setEnd(10.0);
+
+ doubleMatch.setRange(doubleRangeMatch);
+
+ assertFalse(DoubleMatch.isMatch(doubleMatch, 10.0));
+ assertTrue(DoubleMatch.isMatch(doubleMatch, 9.0));
+ }
+
+
+ @Test
+ public void rangeStartEndMatch() {
+ DoubleMatch doubleMatch = new DoubleMatch();
+
+ DoubleRangeMatch doubleRangeMatch = new DoubleRangeMatch();
+ doubleRangeMatch.setStart(5.0);
+ doubleRangeMatch.setEnd(10.0);
+
+ doubleMatch.setRange(doubleRangeMatch);
+
+ assertTrue(DoubleMatch.isMatch(doubleMatch, 5.0));
+ assertFalse(DoubleMatch.isMatch(doubleMatch, 10.0));
+
+ assertFalse(DoubleMatch.isMatch(doubleMatch, 4.9));
+ assertFalse(DoubleMatch.isMatch(doubleMatch, 10.1));
+
+ assertTrue(DoubleMatch.isMatch(doubleMatch, 6.0));
+
+ }
+
+ @Test
+ public void modMatch() {
+ DoubleMatch doubleMatch = new DoubleMatch();
+
+ doubleMatch.setMod(2.0);
+ doubleMatch.setExact(3.0);
+
+ assertFalse(DoubleMatch.isMatch(doubleMatch, 3.0));
+
+ doubleMatch.setExact(1.0);
+
+ assertTrue(DoubleMatch.isMatch(doubleMatch, 1.0));
+ assertFalse(DoubleMatch.isMatch(doubleMatch, 2.0));
+ assertTrue(DoubleMatch.isMatch(doubleMatch, 3.0));
+ }
+
+}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatchTest.java
new file mode 100644
index 0000000..99e704f
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatchTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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.router.mesh.rule.virtualservice.match;
+
+
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+
+public class DubboAttachmentMatchTest {
+
+ @Test
+ public void dubboContextMatch() {
+ DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
+
+ Map<String, StringMatch> dubbocontextMatchMap = new HashMap<>();
+
+ StringMatch nameMatch = new StringMatch();
+ nameMatch.setExact("qinliujie");
+ dubbocontextMatchMap.put("name", nameMatch);
+
+
+ StringMatch machineGroupMatch = new StringMatch();
+ machineGroupMatch.setExact("test_host");
+ dubbocontextMatchMap.put("machineGroup", machineGroupMatch);
+
+ dubboAttachmentMatch.setDubbocontext(dubbocontextMatchMap);
+
+ Map<String, String> invokeDubboContextMap = new HashMap<>();
+ invokeDubboContextMap.put("name", "qinliujie");
+ invokeDubboContextMap.put("machineGroup", "test_host");
+ invokeDubboContextMap.put("other", "other");
+
+ assertTrue(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, new HashMap<>(), invokeDubboContextMap));
+
+
+ Map<String, String> invokeDubboContextMap2 = new HashMap<>();
+ invokeDubboContextMap2.put("name", "jack");
+ invokeDubboContextMap2.put("machineGroup", "test_host");
+ invokeDubboContextMap2.put("other", "other");
+
+ assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, new HashMap<>(), invokeDubboContextMap2));
+
+
+ Map<String, String> invokeDubboContextMap3 = new HashMap<>();
+ invokeDubboContextMap3.put("name", "qinliujie");
+ invokeDubboContextMap3.put("machineGroup", "my_host");
+ invokeDubboContextMap3.put("other", "other");
+
+ assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, new HashMap<>(), invokeDubboContextMap3));
+ }
+
+
+ @Test
+ public void eagleEyeContextMatch() {
+ DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
+
+ Map<String, StringMatch> eagleeyecontextMatchMap = new HashMap<>();
+
+ StringMatch nameMatch = new StringMatch();
+ nameMatch.setExact("qinliujie");
+ eagleeyecontextMatchMap.put("name", nameMatch);
+
+
+ StringMatch machineGroupMatch = new StringMatch();
+ machineGroupMatch.setExact("test_host");
+ eagleeyecontextMatchMap.put("machineGroup", machineGroupMatch);
+
+ dubboAttachmentMatch.setEagleeyecontext(eagleeyecontextMatchMap);
+
+ Map<String, String> invokeEagleEyeContextMap = new HashMap<>();
+ invokeEagleEyeContextMap.put("name", "qinliujie");
+ invokeEagleEyeContextMap.put("machineGroup", "test_host");
+ invokeEagleEyeContextMap.put("other", "other");
+
+ assertTrue(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap, new HashMap<>()));
+
+
+ Map<String, String> invokeEagleEyeContextMap2 = new HashMap<>();
+ invokeEagleEyeContextMap2.put("name", "jack");
+ invokeEagleEyeContextMap2.put("machineGroup", "test_host");
+ invokeEagleEyeContextMap2.put("other", "other");
+
+ assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap2, new HashMap<>()));
+
+
+ Map<String, String> invokeEagleEyeContextMap3 = new HashMap<>();
+ invokeEagleEyeContextMap3.put("name", "qinliujie");
+ invokeEagleEyeContextMap3.put("machineGroup", "my_host");
+ invokeEagleEyeContextMap3.put("other", "other");
+
+ assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap3, new HashMap<>()));
+ }
+
+
+ @Test
+ public void contextMatch() {
+ DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
+
+ {
+ Map<String, StringMatch> eagleeyecontextMatchMap = new HashMap<>();
+ StringMatch nameMatch = new StringMatch();
+ nameMatch.setExact("qinliujie");
+ eagleeyecontextMatchMap.put("name", nameMatch);
+ dubboAttachmentMatch.setEagleeyecontext(eagleeyecontextMatchMap);
+ }
+
+
+ Map<String, String> invokeEagleEyeContextMap = new HashMap<>();
+ invokeEagleEyeContextMap.put("name", "qinliujie");
+ invokeEagleEyeContextMap.put("machineGroup", "test_host");
+ invokeEagleEyeContextMap.put("other", "other");
+
+ //-------
+
+ {
+ Map<String, StringMatch> dubboContextMatchMap = new HashMap<>();
+ StringMatch dpathMatch = new StringMatch();
+ dpathMatch.setExact("PRE");
+ dubboContextMatchMap.put("dpath", dpathMatch);
+ dubboAttachmentMatch.setDubbocontext(dubboContextMatchMap);
+ }
+
+ Map<String, String> invokeDubboContextMap = new HashMap<>();
+ invokeDubboContextMap.put("dpath", "PRE");
+
+
+ assertTrue(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap, invokeDubboContextMap));
+
+
+ Map<String, String> invokeEagleEyeContextMap1 = new HashMap<>();
+ invokeEagleEyeContextMap1.put("name", "jack");
+ invokeEagleEyeContextMap1.put("machineGroup", "test_host");
+ invokeEagleEyeContextMap1.put("other", "other");
+ assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap1, invokeDubboContextMap));
+
+
+ Map<String, String> invokeDubboContextMap1 = new HashMap<>();
+ invokeDubboContextMap1.put("dpath", "PRE-2");
+ assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap, invokeDubboContextMap1));
+
+
+ assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap1, invokeDubboContextMap1));
+
+
+ Map<String, String> invokeEagleEyeContextMap2 = new HashMap<>();
+ invokeEagleEyeContextMap2.put("machineGroup", "test_host");
+ invokeEagleEyeContextMap2.put("other", "other");
+ assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap2, invokeDubboContextMap));
+
+ Map<String, String> invokeDubboContextMap2 = new HashMap<>();
+ assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap, invokeDubboContextMap2));
+
+
+ assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap2, invokeDubboContextMap2));
+
+ }
+}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatchTest.java
new file mode 100644
index 0000000..7c7189b
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatchTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.router.mesh.rule.virtualservice.match;
+
+
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class DubboMethodMatchTest {
+
+ @Test
+ public void nameMatch() {
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+
+ StringMatch nameStringMatch = new StringMatch();
+ nameStringMatch.setExact("sayHello");
+
+ dubboMethodMatch.setName_match(nameStringMatch);
+
+ assertTrue(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{}, new Object[]{}));
+ }
+
+
+ @Test
+ public void argcMatch() {
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+ dubboMethodMatch.setArgc(1);
+
+ assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{}, new Object[]{}));
+ assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{}, null));
+
+ assertTrue(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{}, new Object[]{"1"}));
+ }
+
+ @Test
+ public void argpMatch() {
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+
+ List<StringMatch> argpMatch = new ArrayList<>();
+
+ StringMatch first = new StringMatch();
+ first.setExact("java.lang.Long");
+
+ StringMatch second = new StringMatch();
+ second.setRegex(".*");
+
+ argpMatch.add(first);
+ argpMatch.add(second);
+
+ dubboMethodMatch.setArgp(argpMatch);
+
+
+ assertTrue(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{"java.lang.Long", "java.lang.String"}, new Object[]{}));
+ assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{"java.lang.Long", "java.lang.String", "java.lang.String"}, new Object[]{}));
+ assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{}, new Object[]{}));
+ assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", null, new Object[]{}));
+ }
+
+ @Test
+ public void parametersMatch() {
+
+
+ DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
+
+ List<DubboMethodArg> parametersMatch = new ArrayList<>();
+
+ //----- index 0
+ {
+ DubboMethodArg dubboMethodArg0 = new DubboMethodArg();
+ dubboMethodArg0.setIndex(0);
+
+ ListDoubleMatch listDoubleMatch = new ListDoubleMatch();
+ List<DoubleMatch> oneof = new ArrayList<>();
+
+ DoubleMatch doubleMatch1 = new DoubleMatch();
+ doubleMatch1.setExact(10.0);
+
+ oneof.add(doubleMatch1);
+
+ listDoubleMatch.setOneof(oneof);
+
+ dubboMethodArg0.setNum_value(listDoubleMatch);
+
+ parametersMatch.add(dubboMethodArg0);
+ }
+
+ //-----index 1
+
+ {
+
+ DubboMethodArg dubboMethodArg1 = new DubboMethodArg();
+ dubboMethodArg1.setIndex(1);
+
+ ListStringMatch listStringMatch = new ListStringMatch();
+
+ List<StringMatch> oneof = new ArrayList<>();
+
+ StringMatch stringMatch1 = new StringMatch();
+ stringMatch1.setExact("sayHello");
+
+ oneof.add(stringMatch1);
+
+ listStringMatch.setOneof(oneof);
+
+ dubboMethodArg1.setStr_value(listStringMatch);
+
+ parametersMatch.add(dubboMethodArg1);
+ }
+
+ dubboMethodMatch.setArgs(parametersMatch);
+
+ assertTrue(DubboMethodMatch.isMatch(dubboMethodMatch, "test", new String[]{"int", "java.lang.String"}, new Object[]{10, "sayHello"}));
+ assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "test", new String[]{"int", "java.lang.String"}, new Object[]{10, "sayHi"}));
+
+
+ //-----index 2
+
+ {
+
+ DubboMethodArg dubboMethodArg2 = new DubboMethodArg();
+ dubboMethodArg2.setIndex(2);
+
+ BoolMatch boolMatch = new BoolMatch();
+ boolMatch.setExact(true);
+
+
+ dubboMethodArg2.setBool_value(boolMatch);
+
+ parametersMatch.add(dubboMethodArg2);
+ }
+
+
+ assertTrue(DubboMethodMatch.isMatch(dubboMethodMatch, "test", new String[]{"int", "java.lang.String", "boolean"}, new Object[]{10, "sayHello", true}));
+ assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "test", new String[]{"int", "java.lang.String", "boolean"}, new Object[]{10, "sayHello", false}));
+ }
+}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatchTest.java
new file mode 100644
index 0000000..f3b30b1
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatchTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.router.mesh.rule.virtualservice.match;
+
+
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+
+public class ListDoubleMatchTest {
+
+ @Test
+ public void isMatch() {
+ ListDoubleMatch listDoubleMatch = new ListDoubleMatch();
+ List<DoubleMatch> oneof = new ArrayList<>();
+
+ DoubleMatch doubleMatch1 = new DoubleMatch();
+ doubleMatch1.setExact(10.0);
+
+ DoubleMatch doubleMatch2 = new DoubleMatch();
+ doubleMatch2.setExact(11.0);
+
+ oneof.add(doubleMatch1);
+ oneof.add(doubleMatch2);
+
+ listDoubleMatch.setOneof(oneof);
+
+ assertTrue(ListDoubleMatch.isMatch(listDoubleMatch, 10.0));
+ assertTrue(ListDoubleMatch.isMatch(listDoubleMatch, 11.0));
+ assertFalse(ListDoubleMatch.isMatch(listDoubleMatch, 12.0));
+ }
+}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatchTest.java
new file mode 100644
index 0000000..0561053
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatchTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.router.mesh.rule.virtualservice.match;
+
+
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ListStringMatchTest {
+
+ @Test
+ public void isMatch() {
+ ListStringMatch listStringMatch = new ListStringMatch();
+
+ List<StringMatch> oneof = new ArrayList<>();
+
+ StringMatch stringMatch1 = new StringMatch();
+ stringMatch1.setExact("1");
+
+ StringMatch stringMatch2 = new StringMatch();
+ stringMatch2.setExact("2");
+
+ oneof.add(stringMatch1);
+ oneof.add(stringMatch2);
+
+
+ listStringMatch.setOneof(oneof);
+
+ assertTrue(ListStringMatch.isMatch(listStringMatch, "1"));
+ assertTrue(ListStringMatch.isMatch(listStringMatch, "2"));
+ assertFalse(ListStringMatch.isMatch(listStringMatch, "3"));
+
+ }
+}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatchTest.java
new file mode 100644
index 0000000..13d0225
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatchTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.router.mesh.rule.virtualservice.match;
+
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class StringMatchTest {
+
+ @Test
+ public void exactMatch() {
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setExact("qinliujie");
+
+ assertTrue(StringMatch.isMatch(stringMatch, "qinliujie"));
+ assertFalse(StringMatch.isMatch(stringMatch, "other"));
+ assertFalse(StringMatch.isMatch(stringMatch, null));
+ }
+
+
+ @Test
+ public void prefixMatch() {
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setPrefix("org.apache.dubbo.rpc.cluster.router.mesh");
+
+ assertTrue(StringMatch.isMatch(stringMatch, "org.apache.dubbo.rpc.cluster.router.mesh.test"));
+ assertFalse(StringMatch.isMatch(stringMatch, "com.alibaba.hsf"));
+ assertFalse(StringMatch.isMatch(stringMatch, null));
+ }
+
+
+ @Test
+ public void regxMatch() {
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setRegex("org.apache.dubbo.rpc.cluster.router.mesh.*");
+
+ assertTrue(StringMatch.isMatch(stringMatch, "org.apache.dubbo.rpc.cluster.router.mesh"));
+ assertTrue(StringMatch.isMatch(stringMatch, "org.apache.dubbo.rpc.cluster.router.mesh.test"));
+ assertFalse(StringMatch.isMatch(stringMatch, "com.alibaba.hsf"));
+ assertFalse(StringMatch.isMatch(stringMatch, "com.taobao"));
+ }
+
+
+ @Test
+ public void emptyMatch() {
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setEmpty("empty");
+
+ assertFalse(StringMatch.isMatch(stringMatch, "com.alibaba.hsf"));
+ assertTrue(StringMatch.isMatch(stringMatch, ""));
+ assertTrue(StringMatch.isMatch(stringMatch, null));
+ }
+
+ @Test
+ public void noEmptyMatch() {
+ StringMatch stringMatch = new StringMatch();
+ stringMatch.setNoempty("noempty");
+
+ assertTrue(StringMatch.isMatch(stringMatch, "com.alibaba.hsf"));
+ assertFalse(StringMatch.isMatch(stringMatch, ""));
+ assertFalse(StringMatch.isMatch(stringMatch, null));
+ }
+}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java
new file mode 100644
index 0000000..5193c8d
--- /dev/null
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.router.mesh.util;
+
+import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+
+class VsDestinationGroupRuleDispatcherTest {
+
+ @Test
+ public void post() {
+ VsDestinationGroupRuleDispatcher vsDestinationGroupRuleDispatcher = new VsDestinationGroupRuleDispatcher();
+
+ VsDestinationGroupRuleListener vsDestinationGroupRuleListener = mock(VsDestinationGroupRuleListener.class);
+
+ vsDestinationGroupRuleDispatcher.register(vsDestinationGroupRuleListener);
+
+ vsDestinationGroupRuleDispatcher.post(new VsDestinationGroup());
+ vsDestinationGroupRuleDispatcher.post(new VsDestinationGroup());
+
+ verify(vsDestinationGroupRuleListener, times(2)).onRuleChange(anyObject());
+
+ }
+
+ @Test
+ public void register() {
+ VsDestinationGroupRuleDispatcher vsDestinationGroupRuleDispatcher = new VsDestinationGroupRuleDispatcher();
+
+ VsDestinationGroupRuleListener vsDestinationGroupRuleListener = mock(VsDestinationGroupRuleListener.class);
+
+ assertFalse(vsDestinationGroupRuleDispatcher.register(null));
+ assertTrue(vsDestinationGroupRuleDispatcher.register(vsDestinationGroupRuleListener));
+ assertFalse(vsDestinationGroupRuleDispatcher.register(vsDestinationGroupRuleListener));
+ }
+
+ @Test
+ public void unregister() {
+
+ VsDestinationGroupRuleDispatcher vsDestinationGroupRuleDispatcher = new VsDestinationGroupRuleDispatcher();
+
+ VsDestinationGroupRuleListener vsDestinationGroupRuleListener = mock(VsDestinationGroupRuleListener.class);
+ vsDestinationGroupRuleDispatcher.register(vsDestinationGroupRuleListener);
+
+ vsDestinationGroupRuleDispatcher.post(new VsDestinationGroup());
+
+ vsDestinationGroupRuleDispatcher.unregister(vsDestinationGroupRuleListener);
+ vsDestinationGroupRuleDispatcher.post(new VsDestinationGroup());
+
+ verify(vsDestinationGroupRuleListener, times(1)).onRuleChange(anyObject());
+ }
+}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/resources/DestinationRuleTest.yaml b/dubbo-cluster/src/test/resources/DestinationRuleTest.yaml
new file mode 100644
index 0000000..8f2e135
--- /dev/null
+++ b/dubbo-cluster/src/test/resources/DestinationRuleTest.yaml
@@ -0,0 +1,33 @@
+#
+#
+# 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.
+#
+#
+
+apiVersion: service.dubbo.apache.org/v1alpha1
+kind: DestinationRule
+metadata: { name: demo-route }
+spec:
+ host: demo
+ subsets:
+ - labels: { env-sign: xxx, tag1: hello }
+ name: isolation
+ - labels: { env-sign: yyy }
+ name: testing-trunk
+ - labels: { env-sign: zzz }
+ name: testing
+ trafficPolicy:
+ loadBalancer: { simple: ROUND_ROBIN }
diff --git a/dubbo-cluster/src/test/resources/DestinationRuleTest2.yaml b/dubbo-cluster/src/test/resources/DestinationRuleTest2.yaml
new file mode 100644
index 0000000..178c50e
--- /dev/null
+++ b/dubbo-cluster/src/test/resources/DestinationRuleTest2.yaml
@@ -0,0 +1,58 @@
+#
+#
+# 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.
+#
+#
+
+apiVersion: service.dubbo.apache.org/v1alpha1
+kind: DestinationRule
+metadata: { name: demo-route }
+spec:
+ host: demo
+ subsets:
+ - labels: { env-sign: xxx, tag1: hello }
+ name: isolation
+ - labels: { env-sign: yyy }
+ name: testing-trunk
+ - labels: { env-sign: zzz }
+ name: testing
+ trafficPolicy:
+ loadBalancer: { simple: ROUND_ROBIN }
+
+---
+
+apiVersion: service.dubbo.apache.org/v1alpha1
+kind: VirtualService
+metadata: {name: demo-route}
+spec:
+ dubbo:
+ - routedetail:
+ - match:
+ - sourceLabels: {trafficLabel: xxx}
+ name: xxx-project
+ route:
+ - destination: {host: demo, subset: isolation}
+ - match:
+ - sourceLabels: {trafficLabel: testing-trunk}
+ name: testing-trunk
+ route:
+ - destination: {host: demo, subset: testing-trunk}
+ - name: testing
+ route:
+ - destination: {host: demo, subset: testing}
+ services:
+ - {regex: ccc}
+ hosts: [demo]
diff --git a/dubbo-cluster/src/test/resources/VirtualServiceTest.yaml b/dubbo-cluster/src/test/resources/VirtualServiceTest.yaml
new file mode 100644
index 0000000..4d3454b
--- /dev/null
+++ b/dubbo-cluster/src/test/resources/VirtualServiceTest.yaml
@@ -0,0 +1,41 @@
+#
+#
+# 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.
+#
+#
+
+apiVersion: service.dubbo.apache.org/v1alpha1
+kind: VirtualService
+metadata: {name: demo-route}
+spec:
+ dubbo:
+ - routedetail:
+ - match:
+ - sourceLabels: {trafficLabel: xxx}
+ name: xxx-project
+ route:
+ - destination: {host: demo, subset: isolation}
+ - match:
+ - sourceLabels: {trafficLabel: testing-trunk}
+ name: testing-trunk
+ route:
+ - destination: {host: demo, subset: testing-trunk}
+ - name: testing
+ route:
+ - destination: {host: demo, subset: testing}
+ services:
+ - {regex: ccc}
+ hosts: [demo]