From 7c505f7467a7bbd6ef0daccac6f436673e6ad665 Mon Sep 17 00:00:00 2001 From: qinliujie Date: Tue, 16 Mar 2021 19:51:23 +0800 Subject: [PATCH] Brand new routing rule (#7372) --- dubbo-cluster/pom.xml | 4 +- .../dubbo/registry/AddressListener.java | 0 .../mesh/route/MeshAppRuleListener.java | 98 ++ .../MeshRuleAddressListenerInterceptor.java | 51 + .../router/mesh/route/MeshRuleManager.java | 79 + .../router/mesh/route/MeshRuleRouter.java | 359 +++++ .../mesh/route/MeshRuleRouterFactory.java | 32 + .../cluster/router/mesh/rule/BaseRule.java | 60 + .../router/mesh/rule/VsDestinationGroup.java | 55 + .../destination/ConnectionPoolSettings.java | 22 + .../rule/destination/DestinationRule.java | 41 + .../rule/destination/DestinationRuleSpec.java | 60 + .../router/mesh/rule/destination/Subset.java | 50 + .../mesh/rule/destination/TCPSettings.java | 25 + .../mesh/rule/destination/TcpKeepalive.java | 26 + .../mesh/rule/destination/TrafficPolicy.java | 40 + .../loadbalance/ConsistentHashLB.java | 22 + .../loadbalance/LoadBalancerSettings.java | 48 + .../destination/loadbalance/SimpleLB.java | 26 + .../virtualservice/DubboMatchRequest.java | 130 ++ .../mesh/rule/virtualservice/DubboRoute.java | 62 + .../rule/virtualservice/DubboRouteDetail.java | 62 + .../virtualservice/VirtualServiceRule.java | 41 + .../virtualservice/VirtualServiceSpec.java | 50 + .../destination/DubboDestination.java | 59 + .../destination/DubboRouteDestination.java | 40 + .../rule/virtualservice/match/BoolMatch.java | 38 + .../virtualservice/match/DoubleMatch.java | 63 + .../match/DoubleRangeMatch.java | 53 + .../match/DubboAttachmentMatch.java | 76 + .../virtualservice/match/DubboMethodArg.java | 90 ++ .../match/DubboMethodMatch.java | 128 ++ .../virtualservice/match/ListBoolMatch.java | 22 + .../virtualservice/match/ListDoubleMatch.java | 43 + .../virtualservice/match/ListStringMatch.java | 44 + .../virtualservice/match/StringMatch.java | 105 ++ .../VsDestinationGroupRuleDispatcher.java | 53 + .../util/VsDestinationGroupRuleListener.java | 25 + .../org.apache.dubbo.registry.AddressListener | 1 + ...org.apache.dubbo.rpc.cluster.RouterFactory | 1 + .../mesh/route/MeshAppRuleListenerTest.java | 180 +++ .../mesh/route/MeshRuleManagerTest.java | 160 ++ .../mesh/route/MeshRuleRouterFactoryTest.java | 36 + .../router/mesh/route/MeshRuleRouterTest.java | 1407 +++++++++++++++++ .../router/mesh/rule/DestinationRuleTest.java | 102 ++ .../mesh/rule/VirtualServiceRuleTest.java | 38 + .../virtualservice/DubboMatchRequestTest.java | 140 ++ .../virtualservice/match/BoolMatchTest.java | 42 + .../virtualservice/match/DoubleMatchTest.java | 101 ++ .../match/DubboAttachmentMatchTest.java | 178 +++ .../match/DubboMethodMatchTest.java | 156 ++ .../match/ListDoubleMatchTest.java | 52 + .../match/ListStringMatchTest.java | 54 + .../virtualservice/match/StringMatchTest.java | 81 + .../VsDestinationGroupRuleDispatcherTest.java | 74 + .../test/resources/DestinationRuleTest.yaml | 33 + .../test/resources/DestinationRuleTest2.yaml | 58 + .../test/resources/VirtualServiceTest.yaml | 41 + 58 files changed, 5215 insertions(+), 2 deletions(-) rename {dubbo-registry/dubbo-registry-api => dubbo-cluster}/src/main/java/org/apache/dubbo/registry/AddressListener.java (100%) create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListener.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleAddressListenerInterceptor.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManager.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouter.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactory.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/BaseRule.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VsDestinationGroup.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/ConnectionPoolSettings.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/DestinationRule.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/DestinationRuleSpec.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/Subset.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TCPSettings.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TcpKeepalive.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TrafficPolicy.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/ConsistentHashLB.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/LoadBalancerSettings.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/SimpleLB.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequest.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboRoute.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboRouteDetail.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceRule.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceSpec.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/destination/DubboDestination.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/destination/DubboRouteDestination.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatch.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatch.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleRangeMatch.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatch.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodArg.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatch.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListBoolMatch.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatch.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatch.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatch.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcher.java create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleListener.java create mode 100644 dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.AddressListener create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/DestinationRuleTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatchTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatchTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatchTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatchTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatchTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatchTest.java create mode 100644 dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java create mode 100644 dubbo-cluster/src/test/resources/DestinationRuleTest.yaml create mode 100644 dubbo-cluster/src/test/resources/DestinationRuleTest2.yaml create mode 100644 dubbo-cluster/src/test/resources/VirtualServiceTest.yaml diff --git a/dubbo-cluster/pom.xml b/dubbo-cluster/pom.xml index bd6297430bf..bb588497f60 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. --> - + 4.0.0 org.apache.dubbo @@ -39,7 +40,6 @@ org.yaml snakeyaml - org.apache.curator curator-framework 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% rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java rename 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 00000000000..3946ba4016f --- /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 00000000000..d4cf551af6a --- /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 appMap = new ConcurrentHashMap(); + + @Override + public List notify(List 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 00000000000..aa1630f13cd --- /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 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 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 00000000000..34b9e7f65ad --- /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 sourcesLables = new HashMap<>(); + + protected List> invokerList = new ArrayList<>(); + + Map>> subsetMap; + + private String remoteAppName; + + public MeshRuleRouter(URL url) { + this.url = url; + sourcesLables.putAll(url.getParameters()); + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public List> route(List> invokers, URL url, Invocation invocation) throws RpcException { + + List 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> result; + + Map>> 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 void notify(List> invokers) { + List invokerList = invokers == null ? Collections.emptyList() : invokers; + this.invokerList = invokerList; + registerAppRule(invokerList); + computeSubset(); + } + + + private void registerAppRule(List> 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 getDubboRouteDestination(Invocation invocation) { + + if (vsDestinationGroup != null) { + + List 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 dubboRouteList = spec.getDubbo(); + if (dubboRouteList.size() > 0) { + for (DubboRoute dubboRoute : dubboRouteList) { + List 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 getDubboRouteDestination(DubboRoute dubboRoute, Invocation invocation) { + + List dubboRouteDetailList = dubboRoute.getRoutedetail(); + if (dubboRouteDetailList.size() > 0) { + DubboRouteDetail dubboRouteDetail = findMatchDubboRouteDetail(dubboRouteDetailList, invocation); + if (dubboRouteDetail != null) { + return dubboRouteDetail.getRoute(); + } + } + + return null; + } + + protected DubboRouteDetail findMatchDubboRouteDetail(List dubboRouteDetailList, Invocation invocation) { + + String methodName = invocation.getMethodName(); + String[] parameterTypeList = invocation.getCompatibleParamSignatures(); + Object[] parameters = invocation.getArguments(); + + + for (DubboRouteDetail dubboRouteDetail : dubboRouteDetailList) { + List 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>> subsetMap = computeSubsetMap(invokerList, vsDestinationGroup.getDestinationRuleList()); + + if (subsetMap.size() == 0) { + this.subsetMap = null; + } else { + this.subsetMap = subsetMap; + } + } + + + protected Map>> computeSubsetMap(List> invokers, List destinationRules) { + Map>> subsetMap = new HashMap<>(); + + for (DestinationRule destinationRule : destinationRules) { + DestinationRuleSpec destinationRuleSpec = destinationRule.getSpec(); + String host = destinationRuleSpec.getHost(); + List subsetList = destinationRuleSpec.getSubsets(); + + for (Subset subset : subsetList) { + String subsetName = subset.getName(); + List> subsetInvokerList = new ArrayList<>(); + subsetMap.put(subsetName, subsetInvokerList); + + Map labels = subset.getLabels(); + + for (Invoker invoker : invokers) { + Map parameters = invoker.getUrl().getParameters(); + if (containMapKeyValue(parameters, labels)) { + subsetInvokerList.add(invoker); + } + } + } + } + + return subsetMap; + } + + + protected boolean containMapKeyValue(Map originMap, Map inputMap) { + if (inputMap == null || inputMap.size() == 0) { + return true; + } + + for (Map.Entry 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 sourcesLables) { + this.sourcesLables = sourcesLables; + } + + // just for test + protected void setInvokerList(List> invokerList) { + this.invokerList = invokerList; + } + + // just for test + protected void setSubsetMap(Map>> subsetMap) { + this.subsetMap = subsetMap; + } + + + public VsDestinationGroup getVsDestinationGroup() { + return vsDestinationGroup; + } + + public Map getSourcesLables() { + return sourcesLables; + } + + public List> getInvokerList() { + return invokerList; + } + + public Map>> getSubsetMap() { + return subsetMap; + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactory.java new file mode 100644 index 00000000000..fdbe8e9b608 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactory.java @@ -0,0 +1,32 @@ +/* + * 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.rpc.cluster.Router; +import org.apache.dubbo.rpc.cluster.RouterFactory; + + +@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 00000000000..ffb236f0c23 --- /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 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 getMetadata() { + return metadata; + } + + public void setMetadata(Map 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 00000000000..1d310eed514 --- /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 virtualServiceRuleList = new ArrayList<>(); + private List destinationRuleList = new ArrayList<>(); + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public List getVirtualServiceRuleList() { + return virtualServiceRuleList; + } + + public void setVirtualServiceRuleList(List virtualServiceRuleList) { + this.virtualServiceRuleList = virtualServiceRuleList; + } + + public List getDestinationRuleList() { + return destinationRuleList; + } + + public void setDestinationRuleList(List destinationRuleList) { + this.destinationRuleList = destinationRuleList; + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/ConnectionPoolSettings.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/ConnectionPoolSettings.java new file mode 100644 index 00000000000..32b7af9cd85 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/ConnectionPoolSettings.java @@ -0,0 +1,22 @@ +/* + * 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; + + +public class ConnectionPoolSettings { +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/DestinationRule.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/DestinationRule.java new file mode 100644 index 00000000000..42bc0494556 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/DestinationRule.java @@ -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. + */ + +package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination; + +import org.apache.dubbo.rpc.cluster.router.mesh.rule.BaseRule; + + +public class DestinationRule extends BaseRule { + private DestinationRuleSpec spec; + + 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 00000000000..57d8b063e6d --- /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 subsets; + private TrafficPolicy trafficPolicy; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public List getSubsets() { + return subsets; + } + + public void setSubsets(List 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-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/Subset.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/Subset.java new file mode 100644 index 00000000000..9438ec4dd85 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/Subset.java @@ -0,0 +1,50 @@ +/* + * 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.Map; + + +public class Subset { + private String name; + private Map labels; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Map getLabels() { + return labels; + } + + public void setLabels(Map labels) { + this.labels = labels; + } + + @Override + public String toString() { + return "Subset{" + + "name='" + name + '\'' + + ", labels=" + labels + + '}'; + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TCPSettings.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TCPSettings.java new file mode 100644 index 00000000000..09dc93a8f06 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TCPSettings.java @@ -0,0 +1,25 @@ +/* + * 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; + + +public class TCPSettings { + private int maxConnections; + private int connectTimeout; + private TcpKeepalive tcpKeepalive; +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TcpKeepalive.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TcpKeepalive.java new file mode 100644 index 00000000000..3bc43c7342a --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TcpKeepalive.java @@ -0,0 +1,26 @@ +/* + * 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; + + +public class TcpKeepalive { + private int probes; + private int time; + private int interval; + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TrafficPolicy.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TrafficPolicy.java new file mode 100644 index 00000000000..7f771f0d763 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/TrafficPolicy.java @@ -0,0 +1,40 @@ +/* + * 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance.LoadBalancerSettings; + + +public class TrafficPolicy { + private LoadBalancerSettings loadBalancer; + + 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-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/ConsistentHashLB.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/ConsistentHashLB.java new file mode 100644 index 00000000000..213dfee9e1b --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/ConsistentHashLB.java @@ -0,0 +1,22 @@ +/* + * 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.loadbalance; + + +public class ConsistentHashLB { +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/LoadBalancerSettings.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/LoadBalancerSettings.java new file mode 100644 index 00000000000..1f8b60ed4eb --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/LoadBalancerSettings.java @@ -0,0 +1,48 @@ +/* + * 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.loadbalance; + + +public class LoadBalancerSettings { + private SimpleLB simple; + private ConsistentHashLB consistentHash; + + public SimpleLB getSimple() { + return simple; + } + + 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-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/SimpleLB.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/SimpleLB.java new file mode 100644 index 00000000000..003f1f6a903 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/destination/loadbalance/SimpleLB.java @@ -0,0 +1,26 @@ +/* + * 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.loadbalance; + + +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 00000000000..832bdfebba1 --- /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 sourceLabels; + private DubboAttachmentMatch attachments; + private Map 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 getSourceLabels() { + return sourceLabels; + } + + public void setSourceLabels(Map sourceLabels) { + this.sourceLabels = sourceLabels; + } + + public DubboAttachmentMatch getAttachments() { + return attachments; + } + + public void setAttachments(DubboAttachmentMatch attachments) { + this.attachments = attachments; + } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map 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 sourceLabels, + Map eagleeyeContext, Map dubboContext, + Map headers + ) { + if (dubboMatchRequest.getMethod() != null) { + if (!DubboMethodMatch.isMatch(dubboMatchRequest.getMethod(), methodName, parameterTypeList, parameters)) { + return false; + } + } + + if (dubboMatchRequest.getSourceLabels() != null) { + for (Map.Entry 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 00000000000..d6bf12443c3 --- /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 services; + private List routedetail; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getServices() { + return services; + } + + public void setServices(List services) { + this.services = services; + } + + public List getRoutedetail() { + return routedetail; + } + + public void setRoutedetail(List 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 00000000000..ce425914129 --- /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 match; + private List route; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getMatch() { + return match; + } + + public void setMatch(List match) { + this.match = match; + } + + public List getRoute() { + return route; + } + + public void setRoute(List route) { + this.route = route; + } + + @Override + public String toString() { + return "DubboRouteDetail{" + + "name='" + name + '\'' + + ", match=" + match + + ", route=" + route + + '}'; + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceRule.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceRule.java new file mode 100644 index 00000000000..8f5497a0995 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceRule.java @@ -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. + */ + +package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice; + +import org.apache.dubbo.rpc.cluster.router.mesh.rule.BaseRule; + + +public class VirtualServiceRule extends BaseRule { + private VirtualServiceSpec spec; + + 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-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceSpec.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceSpec.java new file mode 100644 index 00000000000..648fe3be405 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/VirtualServiceSpec.java @@ -0,0 +1,50 @@ +/* + * 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 java.util.List; + + +public class VirtualServiceSpec { + private List hosts; + private List dubbo; + + public List getHosts() { + return hosts; + } + + public void setHosts(List hosts) { + this.hosts = hosts; + } + + public List getDubbo() { + return dubbo; + } + + public void setDubbo(List 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 00000000000..c21a008790b --- /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-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/destination/DubboRouteDestination.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/destination/DubboRouteDestination.java new file mode 100644 index 00000000000..b9588c40cfd --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/destination/DubboRouteDestination.java @@ -0,0 +1,40 @@ +/* + * 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 DubboRouteDestination { + private DubboDestination destination; + private int weight; + + public DubboDestination getDestination() { + return destination; + } + + 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-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatch.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatch.java new file mode 100644 index 00000000000..6d760540850 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatch.java @@ -0,0 +1,38 @@ +/* + * 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 BoolMatch { + private Boolean exact; + + public Boolean getExact() { + return exact; + } + + 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 00000000000..2bd094e04dc --- /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 00000000000..dd693382fdf --- /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 00000000000..b368e5b1af0 --- /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 eagleeyecontext; + private Map dubbocontext; + + public Map getEagleeyecontext() { + return eagleeyecontext; + } + + public void setEagleeyecontext(Map eagleeyecontext) { + this.eagleeyecontext = eagleeyecontext; + } + + public Map getDubbocontext() { + return dubbocontext; + } + + public void setDubbocontext(Map dubbocontext) { + this.dubbocontext = dubbocontext; + } + + public static boolean isMatch(DubboAttachmentMatch dubboAttachmentMatch, Map eagleeyeContext, Map dubboContext) { + if (dubboAttachmentMatch.getDubbocontext() != null) { + for (Map.Entry 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 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 00000000000..5d21572ef23 --- /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 00000000000..e68ea400af2 --- /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 args; + private List argp; + private Map 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 getArgs() { + return args; + } + + public void setArgs(List args) { + this.args = args; + } + + public List getArgp() { + return argp; + } + + public void setArgp(List argp) { + this.argp = argp; + } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map 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 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 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-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListBoolMatch.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListBoolMatch.java new file mode 100644 index 00000000000..9418bdfedca --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListBoolMatch.java @@ -0,0 +1,22 @@ +/* + * 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 ListBoolMatch { +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatch.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatch.java new file mode 100644 index 00000000000..c06397dcee1 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatch.java @@ -0,0 +1,43 @@ +/* + * 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; + + +public class ListDoubleMatch { + private List oneof; + + public List getOneof() { + return oneof; + } + + public void setOneof(List 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-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatch.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatch.java new file mode 100644 index 00000000000..e23d623f1f1 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatch.java @@ -0,0 +1,44 @@ +/* + * 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; + + +public class ListStringMatch { + private List oneof; + + public List getOneof() { + return oneof; + } + + public void setOneof(List 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 00000000000..555ee5bcfa0 --- /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 00000000000..4c1fae25b20 --- /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 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-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleListener.java new file mode 100644 index 00000000000..9e830efa82b --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleListener.java @@ -0,0 +1,25 @@ +/* + * 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; + +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 00000000000..754e5eec66c --- /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 2a807f070ae..1890efca1a3 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 00000000000..8b89daacd59 --- /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 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 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 00000000000..7638c853ddf --- /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 before = ApplicationModel.getEnvironment().getDynamicConfiguration(); + try { + DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class); + + ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration); + + MeshRuleManager.subscribeAppRule("test"); + + ArgumentCaptor 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 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 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 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-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java new file mode 100644 index 00000000000..7bdc47a2b69 --- /dev/null +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java @@ -0,0 +1,36 @@ +/* + * 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.junit.jupiter.api.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +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 00000000000..8262cd6e44d --- /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 originMap = new HashMap<>(); + + originMap.put("key1", "value1"); + originMap.put("key2", "value2"); + originMap.put("key3", "value3"); + + Map 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> invokers = new ArrayList<>(); + + //-- + { + Invoker invoker1 = mock(Invoker.class); + URL invoker1URL = mock(URL.class); + Map 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 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 invoker1Map = new HashMap<>(); + invoker1Map.put("env", "test3"); + + when(invoker1URL.getParameters()).thenReturn(invoker1Map); + when(invoker1.getUrl()).thenReturn(invoker1URL); + + invokers.add(invoker1); + } + + + //-- + + List destinationRules = new ArrayList<>(); + + //-- + { + DestinationRule destinationRule1 = new DestinationRule(); + + DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec(); + destinationRuleSpec.setHost("test1"); + + List subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test1"); + + Map 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 subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test2"); + + Map 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 subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test4"); + + Map subsetTest1Lables = new HashMap<>(); + subsetTest1Lables.put("env", "test4"); + subset.setLabels(subsetTest1Lables); + + subsetList.add(subset); + + destinationRuleSpec.setSubsets(subsetList); + + destinationRule1.setSpec(destinationRuleSpec); + destinationRules.add(destinationRule1); + } + + + //-- + + + Map>> 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> invokers = new ArrayList<>(); + + //-- + { + Invoker invoker1 = mock(Invoker.class); + URL invoker1URL = mock(URL.class); + Map 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 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 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 destinationRules = new ArrayList<>(); + + //-- + { + DestinationRule destinationRule1 = new DestinationRule(); + + DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec(); + destinationRuleSpec.setHost("test1"); + + List subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test1"); + + Map 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 subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test2"); + + Map 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 subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test4"); + + Map 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 dubboRouteDetailList = new ArrayList<>(); + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 dubboRouteDetailList = new ArrayList<>(); + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 dubboRouteDetailList = new ArrayList<>(); + { + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 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 dubboRouteDetailList = new ArrayList<>(); + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 dubboRouteDestinations = new ArrayList<>(); + dubboRouteDestinations.add(new DubboRouteDestination()); + dubboRouteDetail.setRoute(dubboRouteDestinations); + + dubboRouteDetailList.add(dubboRouteDetail); + dubboRoute.setRoutedetail(dubboRouteDetailList); + assertNull(meshRuleRouter.getDubboRouteDestination(dubboRoute, invocation)); + } + + + { + List dubboRouteDetailList = new ArrayList<>(); + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 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 dubboRouteDetailList = new ArrayList<>(); + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 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 dubbo = new ArrayList<>(); + dubbo.add(dubboRoute); + + spec.setDubbo(dubbo); + + virtualServiceRule.setSpec(spec); + DubboRoute result = meshRuleRouter.getDubboRoute(virtualServiceRule, invocation); + + assertNotNull(result); + } + + + { + List dubboRouteDetailList = new ArrayList<>(); + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 dubboRouteDestinations = new ArrayList<>(); + dubboRouteDestinations.add(new DubboRouteDestination()); + dubboRouteDetail.setRoute(dubboRouteDestinations); + + dubboRouteDetailList.add(dubboRouteDetail); + dubboRoute.setRoutedetail(dubboRouteDetailList); + List 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 dubbo = new ArrayList<>(); + dubbo.add(dubboRoute); + + spec.setDubbo(dubbo); + virtualServiceRule.setSpec(spec); + + DubboRoute result = meshRuleRouter.getDubboRoute(virtualServiceRule, invocation); + + assertNull(result); + } + + + { + List dubboRouteDetailList = new ArrayList<>(); + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 dubboRouteDestinations = new ArrayList<>(); + dubboRouteDestinations.add(new DubboRouteDestination()); + dubboRouteDetail.setRoute(dubboRouteDestinations); + + dubboRouteDetailList.add(dubboRouteDetail); + dubboRoute.setRoutedetail(dubboRouteDetailList); + List 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 dubbo = new ArrayList<>(); + dubbo.add(dubboRoute); + + spec.setDubbo(dubbo); + virtualServiceRule.setSpec(spec); + DubboRoute result = meshRuleRouter.getDubboRoute(virtualServiceRule, invocation); + + assertNotNull(result); + } + + { + List dubboRouteDetailList = new ArrayList<>(); + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 dubboRouteDestinations = new ArrayList<>(); + dubboRouteDestinations.add(new DubboRouteDestination()); + dubboRouteDetail.setRoute(dubboRouteDestinations); + + dubboRouteDetailList.add(dubboRouteDetail); + dubboRoute.setRoutedetail(dubboRouteDetailList); + List 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 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> invokers = new ArrayList<>(); + + //-- + { + Invoker invoker1 = mock(Invoker.class); + URL invoker1URL = mock(URL.class); + Map 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 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 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 destinationRules = new ArrayList<>(); + + //-- + { + DestinationRule destinationRule1 = new DestinationRule(); + + DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec(); + destinationRuleSpec.setHost("test1"); + + List subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test1"); + + Map 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 subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test2"); + + Map 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 subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test4"); + + Map 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> 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> invokers = new ArrayList<>(); + + //-- + { + Invoker invoker1 = mock(Invoker.class); + URL invoker1URL = mock(URL.class); + Map 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 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 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 destinationRules = new ArrayList<>(); + + //-- + { + DestinationRule destinationRule1 = new DestinationRule(); + + DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec(); + destinationRuleSpec.setHost("test1"); + + List subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test1"); + + Map 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 subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test2"); + + Map 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 dubboRouteDetailList = new ArrayList<>(); + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 dubboRouteDestinations = new ArrayList<>(); + dubboRouteDestinations.add(new DubboRouteDestination()); + dubboRouteDetail.setRoute(dubboRouteDestinations); + + dubboRouteDetailList.add(dubboRouteDetail); + dubboRoute.setRoutedetail(dubboRouteDetailList); + List 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 dubbo = new ArrayList<>(); + dubbo.add(dubboRoute); + + spec.setDubbo(dubbo); + virtualServiceRule.setSpec(spec); + + List virtualServiceRuleList = new ArrayList<>(); + virtualServiceRuleList.add(virtualServiceRule); + vsDestinationGroup.setVirtualServiceRuleList(virtualServiceRuleList); + meshRuleRouter.computeSubset(); + assertEquals(inputInvokers, meshRuleRouter.route((List) inputInvokers, inputURL, invocation)); + } + + + { + DubboRoute dubboRoute = new DubboRoute(); + List dubboRouteDetailList = new ArrayList<>(); + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 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 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 dubbo = new ArrayList<>(); + dubbo.add(dubboRoute); + + spec.setDubbo(dubbo); + virtualServiceRule.setSpec(spec); + + List 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 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> 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> invokers = new ArrayList<>(); + + //-- + { + Invoker invoker1 = mock(Invoker.class); + URL invoker1URL = mock(URL.class); + Map 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 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 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 destinationRules = new ArrayList<>(); + + //-- + { + DestinationRule destinationRule1 = new DestinationRule(); + + DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec(); + destinationRuleSpec.setHost("test1"); + + List subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test1"); + + Map 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 subsetList = new ArrayList<>(); + + Subset subset = new Subset(); + subset.setName("test2"); + + Map 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 dubboRouteDetailList = new ArrayList<>(); + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 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 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 dubbo = new ArrayList<>(); + dubbo.add(dubboRoute); + + spec.setDubbo(dubbo); + virtualServiceRule.setSpec(spec); + + List 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 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 dubboRouteDetailList = new ArrayList<>(); + DubboRouteDetail dubboRouteDetail = new DubboRouteDetail(); + dubboRouteDetail.setName("test"); + + List 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 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 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 dubbo = new ArrayList<>(); + dubbo.add(dubboRoute); + + spec.setDubbo(dubbo); + virtualServiceRule.setSpec(spec); + + List 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 00000000000..91f5ac73ce6 --- /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-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java new file mode 100644 index 00000000000..ddfb1271d9c --- /dev/null +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java @@ -0,0 +1,38 @@ +/* + * 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.virtualservice.VirtualServiceRule; +import org.junit.jupiter.api.Test; +import org.yaml.snakeyaml.Yaml; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + + +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 00000000000..9bb55b42513 --- /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 sourceLabels = new HashMap<>(); + sourceLabels.put("key1", "value1"); + sourceLabels.put("key2", "value2"); + + dubboMatchRequest.setSourceLabels(sourceLabels); + } + + Map inputSourceLablesMap = new HashMap<>(); + inputSourceLablesMap.put("key1", "value1"); + inputSourceLablesMap.put("key2", "value2"); + inputSourceLablesMap.put("key3", "value3"); + + Map 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 eagleeyecontextMatchMap = new HashMap<>(); + StringMatch nameMatch = new StringMatch(); + nameMatch.setExact("qinliujie"); + eagleeyecontextMatchMap.put("name", nameMatch); + dubboAttachmentMatch.setEagleeyecontext(eagleeyecontextMatchMap); + } + + dubboMatchRequest.setAttachments(dubboAttachmentMatch); + } + + Map 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 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 eagleeyecontextMatchMap = new HashMap<>(); + StringMatch nameMatch = new StringMatch(); + nameMatch.setExact("qinliujie"); + eagleeyecontextMatchMap.put("name", nameMatch); + dubboAttachmentMatch.setEagleeyecontext(eagleeyecontextMatchMap); + } + + + { + Map dubboContextMatchMap = new HashMap<>(); + StringMatch dpathMatch = new StringMatch(); + dpathMatch.setExact("PRE"); + dubboContextMatchMap.put("dpath", dpathMatch); + dubboAttachmentMatch.setDubbocontext(dubboContextMatchMap); + } + + dubboMatchRequest.setAttachments(dubboAttachmentMatch); + } + + + Map invokeDubboContextMap = new HashMap<>(); + invokeDubboContextMap.put("dpath", "PRE"); + + assertTrue(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, invokeEagleEyeContextMap, invokeDubboContextMap, new HashMap())); + + + Map 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-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java new file mode 100644 index 00000000000..72d47748de7 --- /dev/null +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java @@ -0,0 +1,42 @@ +/* + * 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 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 00000000000..aba44bc10c1 --- /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 00000000000..99e704f3f3c --- /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 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 invokeDubboContextMap = new HashMap<>(); + invokeDubboContextMap.put("name", "qinliujie"); + invokeDubboContextMap.put("machineGroup", "test_host"); + invokeDubboContextMap.put("other", "other"); + + assertTrue(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, new HashMap<>(), invokeDubboContextMap)); + + + Map invokeDubboContextMap2 = new HashMap<>(); + invokeDubboContextMap2.put("name", "jack"); + invokeDubboContextMap2.put("machineGroup", "test_host"); + invokeDubboContextMap2.put("other", "other"); + + assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, new HashMap<>(), invokeDubboContextMap2)); + + + Map 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 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 invokeEagleEyeContextMap = new HashMap<>(); + invokeEagleEyeContextMap.put("name", "qinliujie"); + invokeEagleEyeContextMap.put("machineGroup", "test_host"); + invokeEagleEyeContextMap.put("other", "other"); + + assertTrue(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap, new HashMap<>())); + + + Map invokeEagleEyeContextMap2 = new HashMap<>(); + invokeEagleEyeContextMap2.put("name", "jack"); + invokeEagleEyeContextMap2.put("machineGroup", "test_host"); + invokeEagleEyeContextMap2.put("other", "other"); + + assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap2, new HashMap<>())); + + + Map 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 eagleeyecontextMatchMap = new HashMap<>(); + StringMatch nameMatch = new StringMatch(); + nameMatch.setExact("qinliujie"); + eagleeyecontextMatchMap.put("name", nameMatch); + dubboAttachmentMatch.setEagleeyecontext(eagleeyecontextMatchMap); + } + + + Map invokeEagleEyeContextMap = new HashMap<>(); + invokeEagleEyeContextMap.put("name", "qinliujie"); + invokeEagleEyeContextMap.put("machineGroup", "test_host"); + invokeEagleEyeContextMap.put("other", "other"); + + //------- + + { + Map dubboContextMatchMap = new HashMap<>(); + StringMatch dpathMatch = new StringMatch(); + dpathMatch.setExact("PRE"); + dubboContextMatchMap.put("dpath", dpathMatch); + dubboAttachmentMatch.setDubbocontext(dubboContextMatchMap); + } + + Map invokeDubboContextMap = new HashMap<>(); + invokeDubboContextMap.put("dpath", "PRE"); + + + assertTrue(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap, invokeDubboContextMap)); + + + Map invokeEagleEyeContextMap1 = new HashMap<>(); + invokeEagleEyeContextMap1.put("name", "jack"); + invokeEagleEyeContextMap1.put("machineGroup", "test_host"); + invokeEagleEyeContextMap1.put("other", "other"); + assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap1, invokeDubboContextMap)); + + + Map invokeDubboContextMap1 = new HashMap<>(); + invokeDubboContextMap1.put("dpath", "PRE-2"); + assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap, invokeDubboContextMap1)); + + + assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap1, invokeDubboContextMap1)); + + + Map invokeEagleEyeContextMap2 = new HashMap<>(); + invokeEagleEyeContextMap2.put("machineGroup", "test_host"); + invokeEagleEyeContextMap2.put("other", "other"); + assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap2, invokeDubboContextMap)); + + Map 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 00000000000..7c7189bf174 --- /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 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 parametersMatch = new ArrayList<>(); + + //----- index 0 + { + DubboMethodArg dubboMethodArg0 = new DubboMethodArg(); + dubboMethodArg0.setIndex(0); + + ListDoubleMatch listDoubleMatch = new ListDoubleMatch(); + List 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 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 00000000000..f3b30b1f09a --- /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 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 00000000000..056105349de --- /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 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 00000000000..13d02253018 --- /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 00000000000..5193c8d77ac --- /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 00000000000..8f2e13504de --- /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 00000000000..178c50e4cb7 --- /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 00000000000..4d3454bff83 --- /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]