Move Mesh Rule Router to SPI Extensions

This commit is contained in:
heliang 2024-06-22 15:49:11 +08:00
parent 3c4247eb58
commit 5cf472ff07
51 changed files with 0 additions and 4753 deletions

View File

@ -1,186 +0,0 @@
/*
* 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.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
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.state.BitList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.INVALID_APP_NAME;
public class MeshRuleCache<T> {
private final List<String> appList;
private final Map<String, VsDestinationGroup> appToVDGroup;
private final Map<String, Map<String, BitList<Invoker<T>>>> totalSubsetMap;
private final BitList<Invoker<T>> unmatchedInvokers;
private MeshRuleCache(
List<String> appList,
Map<String, VsDestinationGroup> appToVDGroup,
Map<String, Map<String, BitList<Invoker<T>>>> totalSubsetMap,
BitList<Invoker<T>> unmatchedInvokers) {
this.appList = appList;
this.appToVDGroup = appToVDGroup;
this.totalSubsetMap = totalSubsetMap;
this.unmatchedInvokers = unmatchedInvokers;
}
public List<String> getAppList() {
return appList;
}
public Map<String, VsDestinationGroup> getAppToVDGroup() {
return appToVDGroup;
}
public Map<String, Map<String, BitList<Invoker<T>>>> getTotalSubsetMap() {
return totalSubsetMap;
}
public BitList<Invoker<T>> getUnmatchedInvokers() {
return unmatchedInvokers;
}
public VsDestinationGroup getVsDestinationGroup(String appName) {
return appToVDGroup.get(appName);
}
public BitList<Invoker<T>> getSubsetInvokers(String appName, String subset) {
Map<String, BitList<Invoker<T>>> appToSubSets = totalSubsetMap.get(appName);
if (CollectionUtils.isNotEmptyMap(appToSubSets)) {
BitList<Invoker<T>> subsetInvokers = appToSubSets.get(subset);
if (CollectionUtils.isNotEmpty(subsetInvokers)) {
return subsetInvokers;
}
}
return BitList.emptyList();
}
public boolean containsRule() {
return !totalSubsetMap.isEmpty();
}
public static <T> MeshRuleCache<T> build(
String protocolServiceKey,
BitList<Invoker<T>> invokers,
Map<String, VsDestinationGroup> vsDestinationGroupMap) {
if (CollectionUtils.isNotEmptyMap(vsDestinationGroupMap)) {
BitList<Invoker<T>> unmatchedInvokers = new BitList<>(invokers.getOriginList(), true);
Map<String, Map<String, BitList<Invoker<T>>>> totalSubsetMap = new HashMap<>();
for (Invoker<T> invoker : invokers) {
String remoteApplication = invoker.getUrl().getRemoteApplication();
if (StringUtils.isEmpty(remoteApplication) || INVALID_APP_NAME.equals(remoteApplication)) {
unmatchedInvokers.add(invoker);
continue;
}
VsDestinationGroup vsDestinationGroup = vsDestinationGroupMap.get(remoteApplication);
if (vsDestinationGroup == null) {
unmatchedInvokers.add(invoker);
continue;
}
Map<String, BitList<Invoker<T>>> subsetMap =
totalSubsetMap.computeIfAbsent(remoteApplication, (k) -> new HashMap<>());
boolean matched = false;
for (DestinationRule destinationRule : vsDestinationGroup.getDestinationRuleList()) {
DestinationRuleSpec destinationRuleSpec = destinationRule.getSpec();
List<Subset> subsetList = destinationRuleSpec.getSubsets();
for (Subset subset : subsetList) {
String subsetName = subset.getName();
List<Invoker<T>> subsetInvokers = subsetMap.computeIfAbsent(
subsetName, (k) -> new BitList<>(invokers.getOriginList(), true));
Map<String, String> labels = subset.getLabels();
if (isLabelMatch(invoker.getUrl(), protocolServiceKey, labels)) {
subsetInvokers.add(invoker);
matched = true;
}
}
}
if (!matched) {
unmatchedInvokers.add(invoker);
}
}
return new MeshRuleCache<>(
new LinkedList<>(vsDestinationGroupMap.keySet()),
Collections.unmodifiableMap(vsDestinationGroupMap),
Collections.unmodifiableMap(totalSubsetMap),
unmatchedInvokers);
} else {
return new MeshRuleCache<>(
Collections.emptyList(), Collections.emptyMap(), Collections.emptyMap(), invokers);
}
}
public static <T> MeshRuleCache<T> emptyCache() {
return new MeshRuleCache<>(
Collections.emptyList(), Collections.emptyMap(), Collections.emptyMap(), BitList.emptyList());
}
protected static boolean isLabelMatch(URL url, String protocolServiceKey, Map<String, String> inputMap) {
if (inputMap == null || inputMap.size() == 0) {
return true;
}
for (Map.Entry<String, String> entry : inputMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
String originMapValue = url.getOriginalServiceParameter(protocolServiceKey, key);
if (!value.equals(originMapValue)) {
return false;
}
}
return true;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MeshRuleCache<?> ruleCache = (MeshRuleCache<?>) o;
return Objects.equals(appList, ruleCache.appList)
&& Objects.equals(appToVDGroup, ruleCache.appToVDGroup)
&& Objects.equals(totalSubsetMap, ruleCache.totalSubsetMap)
&& Objects.equals(unmatchedInvokers, ruleCache.unmatchedInvokers);
}
@Override
public int hashCode() {
return Objects.hash(appList, appToVDGroup, totalSubsetMap, unmatchedInvokers);
}
}

View File

@ -1,391 +0,0 @@
/*
* 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.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.Holder;
import org.apache.dubbo.common.utils.PojoUtils;
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.RouterSnapshotNode;
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.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.MeshRuleListener;
import org.apache.dubbo.rpc.cluster.router.mesh.util.TracingContextProvider;
import org.apache.dubbo.rpc.cluster.router.state.AbstractStateRouter;
import org.apache.dubbo.rpc.cluster.router.state.BitList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_RECEIVE_RULE;
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.DESTINATION_RULE_KEY;
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.INVALID_APP_NAME;
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.KIND_KEY;
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.VIRTUAL_SERVICE_KEY;
public abstract class MeshRuleRouter<T> extends AbstractStateRouter<T> implements MeshRuleListener {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(MeshRuleRouter.class);
private final Map<String, String> sourcesLabels;
private volatile BitList<Invoker<T>> invokerList = BitList.emptyList();
private volatile Set<String> remoteAppName = Collections.emptySet();
protected MeshRuleManager meshRuleManager;
protected Set<TracingContextProvider> tracingContextProviders;
protected volatile MeshRuleCache<T> meshRuleCache = MeshRuleCache.emptyCache();
public MeshRuleRouter(URL url) {
super(url);
sourcesLabels = Collections.unmodifiableMap(new HashMap<>(url.getParameters()));
this.meshRuleManager = url.getOrDefaultModuleModel().getBeanFactory().getBean(MeshRuleManager.class);
this.tracingContextProviders = url.getOrDefaultModuleModel()
.getExtensionLoader(TracingContextProvider.class)
.getSupportedExtensionInstances();
}
@Override
protected BitList<Invoker<T>> doRoute(
BitList<Invoker<T>> invokers,
URL url,
Invocation invocation,
boolean needToPrintMessage,
Holder<RouterSnapshotNode<T>> nodeHolder,
Holder<String> messageHolder)
throws RpcException {
MeshRuleCache<T> ruleCache = this.meshRuleCache;
if (!ruleCache.containsRule()) {
if (needToPrintMessage) {
messageHolder.set("MeshRuleCache has not been built. Skip route.");
}
return invokers;
}
BitList<Invoker<T>> result = new BitList<>(invokers.getOriginList(), true, invokers.getTailList());
StringBuilder stringBuilder = needToPrintMessage ? new StringBuilder() : null;
// loop each application
for (String appName : ruleCache.getAppList()) {
// find destination by invocation
List<DubboRouteDestination> routeDestination =
getDubboRouteDestination(ruleCache.getVsDestinationGroup(appName), invocation);
if (routeDestination != null) {
// aggregate target invokers
String subset = randomSelectDestination(ruleCache, appName, routeDestination, invokers);
if (subset != null) {
BitList<Invoker<T>> destination = meshRuleCache.getSubsetInvokers(appName, subset);
result = result.or(destination);
if (stringBuilder != null) {
stringBuilder
.append("Match App: ")
.append(appName)
.append(" Subset: ")
.append(subset)
.append(' ');
}
}
}
}
// result = result.or(ruleCache.getUnmatchedInvokers());
// empty protection
if (result.isEmpty()) {
if (needToPrintMessage) {
messageHolder.set("Empty protection after routed.");
}
return invokers;
}
if (needToPrintMessage) {
messageHolder.set(stringBuilder.toString());
}
return invokers.and(result);
}
/**
* Select RouteDestination by Invocation
*/
protected List<DubboRouteDestination> getDubboRouteDestination(
VsDestinationGroup vsDestinationGroup, Invocation invocation) {
if (vsDestinationGroup != null) {
List<VirtualServiceRule> virtualServiceRuleList = vsDestinationGroup.getVirtualServiceRuleList();
if (CollectionUtils.isNotEmpty(virtualServiceRuleList)) {
for (VirtualServiceRule virtualServiceRule : virtualServiceRuleList) {
// match virtual service (by serviceName)
DubboRoute dubboRoute = getDubboRoute(virtualServiceRule, invocation);
if (dubboRoute != null) {
// match route detail (by params)
return getDubboRouteDestination(dubboRoute, invocation);
}
}
}
}
return null;
}
/**
* Match virtual service (by serviceName)
*/
protected DubboRoute getDubboRoute(VirtualServiceRule virtualServiceRule, Invocation invocation) {
String serviceName = invocation.getServiceName();
VirtualServiceSpec spec = virtualServiceRule.getSpec();
List<DubboRoute> dubboRouteList = spec.getDubbo();
if (CollectionUtils.isNotEmpty(dubboRouteList)) {
for (DubboRoute dubboRoute : dubboRouteList) {
List<StringMatch> stringMatchList = dubboRoute.getServices();
if (CollectionUtils.isEmpty(stringMatchList)) {
return dubboRoute;
}
for (StringMatch stringMatch : stringMatchList) {
if (stringMatch.isMatch(serviceName)) {
return dubboRoute;
}
}
}
}
return null;
}
/**
* Match route detail (by params)
*/
protected List<DubboRouteDestination> getDubboRouteDestination(DubboRoute dubboRoute, Invocation invocation) {
List<DubboRouteDetail> dubboRouteDetailList = dubboRoute.getRoutedetail();
if (CollectionUtils.isNotEmpty(dubboRouteDetailList)) {
for (DubboRouteDetail dubboRouteDetail : dubboRouteDetailList) {
List<DubboMatchRequest> matchRequestList = dubboRouteDetail.getMatch();
if (CollectionUtils.isEmpty(matchRequestList)) {
return dubboRouteDetail.getRoute();
}
if (matchRequestList.stream()
.allMatch(request -> request.isMatch(invocation, sourcesLabels, tracingContextProviders))) {
return dubboRouteDetail.getRoute();
}
}
}
return null;
}
/**
* Find out target invokers from RouteDestination
*/
protected String randomSelectDestination(
MeshRuleCache<T> meshRuleCache,
String appName,
List<DubboRouteDestination> routeDestination,
BitList<Invoker<T>> availableInvokers)
throws RpcException {
// randomly select one DubboRouteDestination from list by weight
int totalWeight = 0;
for (DubboRouteDestination dubboRouteDestination : routeDestination) {
totalWeight += Math.max(dubboRouteDestination.getWeight(), 1);
}
int target = ThreadLocalRandom.current().nextInt(totalWeight);
for (DubboRouteDestination destination : routeDestination) {
target -= Math.max(destination.getWeight(), 1);
if (target <= 0) {
// match weight
String result =
computeDestination(meshRuleCache, appName, destination.getDestination(), availableInvokers);
if (result != null) {
return result;
}
}
}
// fall back
for (DubboRouteDestination destination : routeDestination) {
String result = computeDestination(meshRuleCache, appName, destination.getDestination(), availableInvokers);
if (result != null) {
return result;
}
}
return null;
}
/**
* Compute Destination Subset
*/
protected String computeDestination(
MeshRuleCache<T> meshRuleCache,
String appName,
DubboDestination dubboDestination,
BitList<Invoker<T>> availableInvokers)
throws RpcException {
String subset = dubboDestination.getSubset();
do {
BitList<Invoker<T>> result = meshRuleCache.getSubsetInvokers(appName, subset);
if (CollectionUtils.isNotEmpty(result)
&& !availableInvokers.clone().and(result).isEmpty()) {
return subset;
}
// fall back
DubboRouteDestination dubboRouteDestination = dubboDestination.getFallback();
if (dubboRouteDestination == null) {
break;
}
dubboDestination = dubboRouteDestination.getDestination();
if (dubboDestination == null) {
break;
}
subset = dubboDestination.getSubset();
} while (true);
return null;
}
@Override
public void notify(BitList<Invoker<T>> invokers) {
BitList<Invoker<T>> invokerList = invokers == null ? BitList.emptyList() : invokers;
this.invokerList = invokerList.clone();
registerAppRule(invokerList);
computeSubset(this.meshRuleCache.getAppToVDGroup());
}
private void registerAppRule(BitList<Invoker<T>> invokers) {
Set<String> currentApplication = new HashSet<>();
if (CollectionUtils.isNotEmpty(invokers)) {
for (Invoker<T> invoker : invokers) {
String applicationName = invoker.getUrl().getRemoteApplication();
if (StringUtils.isNotEmpty(applicationName) && !INVALID_APP_NAME.equals(applicationName)) {
currentApplication.add(applicationName);
}
}
}
if (!remoteAppName.equals(currentApplication)) {
synchronized (this) {
Set<String> current = new HashSet<>(currentApplication);
Set<String> previous = new HashSet<>(remoteAppName);
previous.removeAll(currentApplication);
current.removeAll(remoteAppName);
for (String app : current) {
meshRuleManager.register(app, this);
}
for (String app : previous) {
meshRuleManager.unregister(app, this);
}
remoteAppName = currentApplication;
}
}
}
@Override
public synchronized void onRuleChange(String appName, List<Map<String, Object>> rules) {
// only update specified app's rule
Map<String, VsDestinationGroup> appToVDGroup = new ConcurrentHashMap<>(this.meshRuleCache.getAppToVDGroup());
try {
VsDestinationGroup vsDestinationGroup = new VsDestinationGroup();
vsDestinationGroup.setAppName(appName);
for (Map<String, Object> rule : rules) {
if (DESTINATION_RULE_KEY.equals(rule.get(KIND_KEY))) {
DestinationRule destinationRule = PojoUtils.mapToPojo(rule, DestinationRule.class);
vsDestinationGroup.getDestinationRuleList().add(destinationRule);
} else if (VIRTUAL_SERVICE_KEY.equals(rule.get(KIND_KEY))) {
VirtualServiceRule virtualServiceRule = PojoUtils.mapToPojo(rule, VirtualServiceRule.class);
vsDestinationGroup.getVirtualServiceRuleList().add(virtualServiceRule);
}
}
if (vsDestinationGroup.isValid()) {
appToVDGroup.put(appName, vsDestinationGroup);
}
} catch (Throwable t) {
logger.error(
CLUSTER_FAILED_RECEIVE_RULE,
"failed to parse mesh route rule",
"",
"Error occurred when parsing rule component.",
t);
}
computeSubset(appToVDGroup);
}
@Override
public synchronized void clearRule(String appName) {
Map<String, VsDestinationGroup> appToVDGroup = new ConcurrentHashMap<>(this.meshRuleCache.getAppToVDGroup());
appToVDGroup.remove(appName);
computeSubset(appToVDGroup);
}
protected void computeSubset(Map<String, VsDestinationGroup> vsDestinationGroupMap) {
this.meshRuleCache =
MeshRuleCache.build(getUrl().getProtocolServiceKey(), this.invokerList, vsDestinationGroupMap);
}
@Override
public void stop() {
for (String app : remoteAppName) {
meshRuleManager.unregister(app, this);
}
}
/**
* for ut only
*/
@Deprecated
public Set<String> getRemoteAppName() {
return remoteAppName;
}
/**
* for ut only
*/
@Deprecated
public BitList<Invoker<T>> getInvokerList() {
return invokerList;
}
/**
* for ut only
*/
@Deprecated
public MeshRuleCache<T> getMeshRuleCache() {
return meshRuleCache;
}
}

View File

@ -1,33 +0,0 @@
/*
* 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 static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.STANDARD_ROUTER_KEY;
public class StandardMeshRuleRouter<T> extends MeshRuleRouter<T> {
public StandardMeshRuleRouter(URL url) {
super(url);
}
@Override
public String ruleSuffix() {
return STANDARD_ROUTER_KEY;
}
}

View File

@ -1,30 +0,0 @@
/*
* 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.state.StateRouter;
import org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory;
@Activate(order = -50)
public class StandardMeshRuleRouterFactory implements StateRouterFactory {
@Override
public <T> StateRouter<T> getRouter(Class<T> interfaceClass, URL url) {
return new StandardMeshRuleRouter<>(url);
}
}

View File

@ -1,57 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule;
import java.util.Map;
public class BaseRule {
private String apiVersion;
private String kind;
private Map<String, String> metadata;
public String getApiVersion() {
return apiVersion;
}
public void setApiVersion(String apiVersion) {
this.apiVersion = apiVersion;
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public Map<String, String> getMetadata() {
return metadata;
}
public void setMetadata(Map<String, String> metadata) {
this.metadata = metadata;
}
@Override
public String toString() {
return "BaseRule{" + "apiVersion='"
+ apiVersion + '\'' + ", kind='"
+ kind + '\'' + ", metadata="
+ metadata + '}';
}
}

View File

@ -1,57 +0,0 @@
/*
* 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.LinkedList;
import java.util.List;
public class VsDestinationGroup {
private String appName;
private List<VirtualServiceRule> virtualServiceRuleList = new LinkedList<>();
private List<DestinationRule> destinationRuleList = new LinkedList<>();
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public List<VirtualServiceRule> getVirtualServiceRuleList() {
return virtualServiceRuleList;
}
public void setVirtualServiceRuleList(List<VirtualServiceRule> virtualServiceRuleList) {
this.virtualServiceRuleList = virtualServiceRuleList;
}
public List<DestinationRule> getDestinationRuleList() {
return destinationRuleList;
}
public void setDestinationRuleList(List<DestinationRule> destinationRuleList) {
this.destinationRuleList = destinationRuleList;
}
public boolean isValid() {
return virtualServiceRuleList.size() > 0 && destinationRuleList.size() > 0;
}
}

View File

@ -1,19 +0,0 @@
/*
* 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 {}

View File

@ -1,36 +0,0 @@
/*
* 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 + '}';
}
}

View File

@ -1,57 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
import java.util.List;
public class DestinationRuleSpec {
private String host;
private List<Subset> subsets;
private TrafficPolicy trafficPolicy;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public List<Subset> getSubsets() {
return subsets;
}
public void setSubsets(List<Subset> subsets) {
this.subsets = subsets;
}
public TrafficPolicy getTrafficPolicy() {
return trafficPolicy;
}
public void setTrafficPolicy(TrafficPolicy trafficPolicy) {
this.trafficPolicy = trafficPolicy;
}
@Override
public String toString() {
return "DestinationRuleSpec{" + "host='"
+ host + '\'' + ", subsets="
+ subsets + ", trafficPolicy="
+ trafficPolicy + '}';
}
}

View File

@ -1,45 +0,0 @@
/*
* 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<String, String> labels;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<String, String> getLabels() {
return labels;
}
public void setLabels(Map<String, String> labels) {
this.labels = labels;
}
@Override
public String toString() {
return "Subset{" + "name='" + name + '\'' + ", labels=" + labels + '}';
}
}

View File

@ -1,23 +0,0 @@
/*
* 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;
}

View File

@ -1,23 +0,0 @@
/*
* 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;
}

View File

@ -1,36 +0,0 @@
/*
* 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 + '}';
}
}

View File

@ -1,19 +0,0 @@
/*
* 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 {}

View File

@ -1,43 +0,0 @@
/*
* 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 + '}';
}
}

View File

@ -1,24 +0,0 @@
/*
* 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
}

View File

@ -1,113 +0,0 @@
/*
* 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.Invocation;
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.apache.dubbo.rpc.cluster.router.mesh.util.TracingContextProvider;
import java.util.Map;
import java.util.Set;
public class DubboMatchRequest {
private String name;
private DubboMethodMatch method;
private Map<String, String> sourceLabels;
private DubboAttachmentMatch attachments;
private Map<String, StringMatch> headers;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public DubboMethodMatch getMethod() {
return method;
}
public void setMethod(DubboMethodMatch method) {
this.method = method;
}
public Map<String, String> getSourceLabels() {
return sourceLabels;
}
public void setSourceLabels(Map<String, String> sourceLabels) {
this.sourceLabels = sourceLabels;
}
public DubboAttachmentMatch getAttachments() {
return attachments;
}
public void setAttachments(DubboAttachmentMatch attachments) {
this.attachments = attachments;
}
public Map<String, StringMatch> getHeaders() {
return headers;
}
public void setHeaders(Map<String, StringMatch> headers) {
this.headers = headers;
}
@Override
public String toString() {
return "DubboMatchRequest{" + "name='"
+ name + '\'' + ", method="
+ method + ", sourceLabels="
+ sourceLabels + ", attachments="
+ attachments + ", headers="
+ headers + '}';
}
public boolean isMatch(
Invocation invocation, Map<String, String> sourceLabels, Set<TracingContextProvider> contextProviders) {
// Match method
if (getMethod() != null) {
if (!getMethod().isMatch(invocation)) {
return false;
}
}
// Match Source Labels
if (getSourceLabels() != null) {
for (Map.Entry<String, String> entry : getSourceLabels().entrySet()) {
String value = sourceLabels.get(entry.getKey());
if (!entry.getValue().equals(value)) {
return false;
}
}
}
// Match attachment
if (getAttachments() != null) {
return getAttachments().isMatch(invocation, contextProviders);
}
// TODO Match headers
return true;
}
}

View File

@ -1,56 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
import java.util.List;
public class DubboRoute {
private String name;
private List<StringMatch> services;
private List<DubboRouteDetail> routedetail;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<StringMatch> getServices() {
return services;
}
public void setServices(List<StringMatch> services) {
this.services = services;
}
public List<DubboRouteDetail> getRoutedetail() {
return routedetail;
}
public void setRoutedetail(List<DubboRouteDetail> routedetail) {
this.routedetail = routedetail;
}
@Override
public String toString() {
return "DubboRoute{" + "name='" + name + '\'' + ", services=" + services + ", routedetail=" + routedetail + '}';
}
}

View File

@ -1,56 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination.DubboRouteDestination;
import java.util.List;
public class DubboRouteDetail {
private String name;
private List<DubboMatchRequest> match;
private List<DubboRouteDestination> route;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<DubboMatchRequest> getMatch() {
return match;
}
public void setMatch(List<DubboMatchRequest> match) {
this.match = match;
}
public List<DubboRouteDestination> getRoute() {
return route;
}
public void setRoute(List<DubboRouteDestination> route) {
this.route = route;
}
@Override
public String toString() {
return "DubboRouteDetail{" + "name='" + name + '\'' + ", match=" + match + ", route=" + route + '}';
}
}

View File

@ -1,36 +0,0 @@
/*
* 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 + '}';
}
}

View File

@ -1,45 +0,0 @@
/*
* 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<String> hosts;
private List<DubboRoute> dubbo;
public List<String> getHosts() {
return hosts;
}
public void setHosts(List<String> hosts) {
this.hosts = hosts;
}
public List<DubboRoute> getDubbo() {
return dubbo;
}
public void setDubbo(List<DubboRoute> dubbo) {
this.dubbo = dubbo;
}
@Override
public String toString() {
return "VirtualServiceSpec{" + "hosts=" + hosts + ", dubbo=" + dubbo + '}';
}
}

View File

@ -1,56 +0,0 @@
/*
* 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;
}
}

View File

@ -1,38 +0,0 @@
/*
* 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;
}
}

View File

@ -1,87 +0,0 @@
/*
* 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.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import java.net.UnknownHostException;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_EXEC_CONDITION_ROUTER;
import static org.apache.dubbo.common.utils.NetUtils.matchIpExpression;
import static org.apache.dubbo.common.utils.UrlUtils.isMatchGlobPattern;
public class AddressMatch {
public static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(AddressMatch.class);
private String wildcard;
private String cird;
private String exact;
public String getWildcard() {
return wildcard;
}
public void setWildcard(String wildcard) {
this.wildcard = wildcard;
}
public String getCird() {
return cird;
}
public void setCird(String cird) {
this.cird = cird;
}
public String getExact() {
return exact;
}
public void setExact(String exact) {
this.exact = exact;
}
public boolean isMatch(String input) {
if (getCird() != null && input != null) {
try {
return input.equals(getCird()) || matchIpExpression(getCird(), input);
} catch (UnknownHostException e) {
logger.error(
CLUSTER_FAILED_EXEC_CONDITION_ROUTER,
"Executing routing rule match expression error.",
"",
String.format(
"Error trying to match cird formatted address %s with input %s in AddressMatch.",
getCird(), input),
e);
}
}
if (getWildcard() != null && input != null) {
if (ANYHOST_VALUE.equals(getWildcard()) || ANY_VALUE.equals(getWildcard())) {
return true;
}
// FIXME
return isMatchGlobPattern(getWildcard(), input);
}
if (getExact() != null && input != null) {
return input.equals(getExact());
}
return false;
}
}

View File

@ -1,36 +0,0 @@
/*
* 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 boolean isMatch(boolean input) {
if (exact != null) {
return input == exact;
}
return false;
}
}

View File

@ -1,60 +0,0 @@
/*
* 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 boolean isMatch(Double input) {
if (exact != null && mod == null) {
return input.equals(exact);
} else if (range != null) {
return range.isMatch(input);
} else if (exact != null) {
Double result = input % mod;
return result.equals(exact);
}
return false;
}
}

View File

@ -1,50 +0,0 @@
/*
* 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 boolean isMatch(Double input) {
if (start != null && end != null) {
return input.compareTo(start) >= 0 && input.compareTo(end) < 0;
} else if (start != null) {
return input.compareTo(start) >= 0;
} else if (end != null) {
return input.compareTo(end) < 0;
} else {
return false;
}
}
}

View File

@ -1,73 +0,0 @@
/*
* 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.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.cluster.router.mesh.util.TracingContextProvider;
import java.util.Map;
import java.util.Set;
public class DubboAttachmentMatch {
private Map<String, StringMatch> tracingContext;
private Map<String, StringMatch> dubboContext;
public Map<String, StringMatch> getTracingContext() {
return tracingContext;
}
public void setTracingContext(Map<String, StringMatch> tracingContext) {
this.tracingContext = tracingContext;
}
public Map<String, StringMatch> getDubboContext() {
return dubboContext;
}
public void setDubboContext(Map<String, StringMatch> dubboContext) {
this.dubboContext = dubboContext;
}
public boolean isMatch(Invocation invocation, Set<TracingContextProvider> contextProviders) {
// Match Dubbo Context
if (dubboContext != null) {
for (Map.Entry<String, StringMatch> entry : dubboContext.entrySet()) {
String key = entry.getKey();
if (!entry.getValue().isMatch(invocation.getAttachment(key))) {
return false;
}
}
}
// Match Tracing Context
if (tracingContext != null) {
for (Map.Entry<String, StringMatch> entry : tracingContext.entrySet()) {
String key = entry.getKey();
boolean match = false;
for (TracingContextProvider contextProvider : contextProviders) {
if (entry.getValue().isMatch(contextProvider.getValue(invocation, key))) {
match = true;
}
}
if (!match) {
return false;
}
}
}
return true;
}
}

View File

@ -1,87 +0,0 @@
/*
* 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 boolean isMatch(Object input) {
if (str_value != null) {
return input instanceof String && str_value.isMatch((String) input);
} else if (num_value != null) {
return num_value.isMatch(Double.valueOf(input.toString()));
} else if (bool_value != null) {
return input instanceof Boolean && bool_value.isMatch((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 + '}';
}
}

View File

@ -1,133 +0,0 @@
/*
* 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.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.support.RpcUtils;
import java.util.List;
import java.util.Map;
public class DubboMethodMatch {
private StringMatch name_match;
private Integer argc;
private List<DubboMethodArg> args;
private List<StringMatch> argp;
private Map<String, StringMatch> headers;
public StringMatch getName_match() {
return name_match;
}
public void setName_match(StringMatch name_match) {
this.name_match = name_match;
}
public Integer getArgc() {
return argc;
}
public void setArgc(Integer argc) {
this.argc = argc;
}
public List<DubboMethodArg> getArgs() {
return args;
}
public void setArgs(List<DubboMethodArg> args) {
this.args = args;
}
public List<StringMatch> getArgp() {
return argp;
}
public void setArgp(List<StringMatch> argp) {
this.argp = argp;
}
public Map<String, StringMatch> getHeaders() {
return headers;
}
public void setHeaders(Map<String, StringMatch> headers) {
this.headers = headers;
}
@Override
public String toString() {
return "DubboMethodMatch{" + "name_match="
+ name_match + ", argc="
+ argc + ", args="
+ args + ", argp="
+ argp + ", headers="
+ headers + '}';
}
public boolean isMatch(Invocation invocation) {
StringMatch nameMatch = getName_match();
if (nameMatch != null && !nameMatch.isMatch(RpcUtils.getMethodName(invocation))) {
return false;
}
Integer argc = getArgc();
Object[] arguments = invocation.getArguments();
if (argc != null
&& ((argc != 0 && (arguments == null || arguments.length == 0)) || (argc != arguments.length))) {
return false;
}
List<StringMatch> argp = getArgp();
Class<?>[] parameterTypes = invocation.getParameterTypes();
if (argp != null && argp.size() > 0) {
if (parameterTypes == null || parameterTypes.length == 0) {
return false;
}
if (argp.size() != parameterTypes.length) {
return false;
}
for (int index = 0; index < argp.size(); index++) {
boolean match = argp.get(index).isMatch(parameterTypes[index].getName())
|| argp.get(index).isMatch(parameterTypes[index].getSimpleName());
if (!match) {
return false;
}
}
}
List<DubboMethodArg> args = getArgs();
if (args != null && args.size() > 0) {
if (arguments == null || arguments.length == 0) {
return false;
}
for (DubboMethodArg dubboMethodArg : args) {
int index = dubboMethodArg.getIndex();
if (index >= arguments.length) {
throw new IndexOutOfBoundsException("DubboMethodArg index >= parameters.length");
}
if (!dubboMethodArg.isMatch(arguments[index])) {
return false;
}
}
}
return true;
}
}

View File

@ -1,41 +0,0 @@
/*
* 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 ListBoolMatch {
private List<BoolMatch> oneof;
public List<BoolMatch> getOneof() {
return oneof;
}
public void setOneof(List<BoolMatch> oneof) {
this.oneof = oneof;
}
public boolean isMatch(boolean input) {
for (BoolMatch boolMatch : oneof) {
if (boolMatch.isMatch(input)) {
return true;
}
}
return false;
}
}

View File

@ -1,41 +0,0 @@
/*
* 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<DoubleMatch> oneof;
public List<DoubleMatch> getOneof() {
return oneof;
}
public void setOneof(List<DoubleMatch> oneof) {
this.oneof = oneof;
}
public boolean isMatch(Double input) {
for (DoubleMatch doubleMatch : oneof) {
if (doubleMatch.isMatch(input)) {
return true;
}
}
return false;
}
}

View File

@ -1,41 +0,0 @@
/*
* 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<StringMatch> oneof;
public List<StringMatch> getOneof() {
return oneof;
}
public void setOneof(List<StringMatch> oneof) {
this.oneof = oneof;
}
public boolean isMatch(String input) {
for (StringMatch stringMatch : oneof) {
if (stringMatch.isMatch(input)) {
return true;
}
}
return false;
}
}

View File

@ -1,105 +0,0 @@
/*
* 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 static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
public class StringMatch {
private String exact;
private String prefix;
private String regex;
private String noempty;
private String empty;
private String wildcard;
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 String getWildcard() {
return wildcard;
}
public void setWildcard(String wildcard) {
this.wildcard = wildcard;
}
public boolean isMatch(String input) {
if (getExact() != null && input != null) {
return input.equals(getExact());
} else if (getPrefix() != null && input != null) {
return input.startsWith(getPrefix());
} else if (getRegex() != null && input != null) {
return input.matches(getRegex());
} else if (getWildcard() != null && input != null) {
// only supports "*"
return input.equals(getWildcard()) || ANY_VALUE.equals(getWildcard());
} else if (getEmpty() != null) {
return input == null || "".equals(input);
} else if (getNoempty() != null) {
return input != null && input.length() > 0;
} else {
return false;
}
}
@Override
public String toString() {
return "StringMatch{" + "exact='"
+ exact + '\'' + ", prefix='"
+ prefix + '\'' + ", regex='"
+ regex + '\'' + ", noempty='"
+ noempty + '\'' + ", empty='"
+ empty + '\'' + '}';
}
}

View File

@ -1,392 +0,0 @@
/*
* 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.config.configcenter.ConfigChangeType;
import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
import org.apache.dubbo.rpc.cluster.router.mesh.util.MeshRuleListener;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.MESH_RULE_DATA_ID_SUFFIX;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
class MeshAppRuleListenerTest {
private static final String rule1 = "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";
private static final String rule2 = "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";
private static final String rule3 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: DestinationRule\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";
private static final String rule4 = "apiVersionservice.dubbo.apache.org/v1alpha1\n";
private static final String rule5 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: DestinationRule\n"
+ "metadata: { name: demo-route.Type1 }\n"
+ "spec:\n"
+ " host: demo\n"
+ "\n";
private static final String rule6 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: VirtualService\n"
+ "metadata: { name: demo-route.Type1 }\n"
+ "spec:\n"
+ " hosts: [demo]\n";
private static final String rule7 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: DestinationRule\n"
+ "metadata: { name: demo-route.Type2 }\n"
+ "spec:\n"
+ " host: demo\n"
+ "\n";
private static final String rule8 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: VirtualService\n"
+ "metadata: { name: demo-route.Type2 }\n"
+ "spec:\n"
+ " hosts: [demo]\n";
@Test
void testStandard() {
MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener("demo-route");
StandardMeshRuleRouter standardMeshRuleRouter = Mockito.spy(new StandardMeshRuleRouter(URL.valueOf("")));
meshAppRuleListener.register(standardMeshRuleRouter);
meshAppRuleListener.receiveConfigInfo(rule1 + "---\n" + rule2);
ArgumentCaptor<String> appCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<List<Map<String, Object>>> ruleCaptor = ArgumentCaptor.forClass(List.class);
verify(standardMeshRuleRouter, times(1)).onRuleChange(appCaptor.capture(), ruleCaptor.capture());
List<Map<String, Object>> rulesReceived = ruleCaptor.getValue();
assertEquals(2, rulesReceived.size());
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule1)));
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule2)));
Assertions.assertEquals("demo-route", appCaptor.getValue());
meshAppRuleListener.receiveConfigInfo("");
verify(standardMeshRuleRouter, times(1)).clearRule("demo-route");
}
@Test
void register() {
MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener("demo-route");
StandardMeshRuleRouter standardMeshRuleRouter1 = Mockito.spy(new StandardMeshRuleRouter(URL.valueOf("")));
StandardMeshRuleRouter standardMeshRuleRouter2 = Mockito.spy(new StandardMeshRuleRouter(URL.valueOf("")));
meshAppRuleListener.register(standardMeshRuleRouter1);
Assertions.assertEquals(
1,
meshAppRuleListener
.getMeshRuleDispatcher()
.getListenerMap()
.get(MeshRuleConstants.STANDARD_ROUTER_KEY)
.size());
meshAppRuleListener.receiveConfigInfo(rule1 + "---\n" + rule2);
meshAppRuleListener.register(standardMeshRuleRouter2);
Assertions.assertEquals(
2,
meshAppRuleListener
.getMeshRuleDispatcher()
.getListenerMap()
.get(MeshRuleConstants.STANDARD_ROUTER_KEY)
.size());
ArgumentCaptor<String> appCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<List<Map<String, Object>>> ruleCaptor = ArgumentCaptor.forClass(List.class);
verify(standardMeshRuleRouter1, times(1)).onRuleChange(appCaptor.capture(), ruleCaptor.capture());
List<Map<String, Object>> rulesReceived = ruleCaptor.getValue();
assertEquals(2, rulesReceived.size());
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule1)));
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule2)));
Assertions.assertEquals("demo-route", appCaptor.getValue());
verify(standardMeshRuleRouter2, times(1)).onRuleChange(appCaptor.capture(), ruleCaptor.capture());
rulesReceived = ruleCaptor.getValue();
assertEquals(2, rulesReceived.size());
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule1)));
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule2)));
Assertions.assertEquals("demo-route", appCaptor.getValue());
}
@Test
void unregister() {
MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener("demo-route");
StandardMeshRuleRouter standardMeshRuleRouter1 = Mockito.spy(new StandardMeshRuleRouter(URL.valueOf("")));
StandardMeshRuleRouter standardMeshRuleRouter2 = Mockito.spy(new StandardMeshRuleRouter(URL.valueOf("")));
meshAppRuleListener.register(standardMeshRuleRouter1);
Assertions.assertEquals(
1,
meshAppRuleListener
.getMeshRuleDispatcher()
.getListenerMap()
.get(MeshRuleConstants.STANDARD_ROUTER_KEY)
.size());
meshAppRuleListener.receiveConfigInfo(rule1 + "---\n" + rule2);
meshAppRuleListener.register(standardMeshRuleRouter2);
Assertions.assertEquals(
2,
meshAppRuleListener
.getMeshRuleDispatcher()
.getListenerMap()
.get(MeshRuleConstants.STANDARD_ROUTER_KEY)
.size());
meshAppRuleListener.unregister(standardMeshRuleRouter1);
Assertions.assertEquals(
1,
meshAppRuleListener
.getMeshRuleDispatcher()
.getListenerMap()
.get(MeshRuleConstants.STANDARD_ROUTER_KEY)
.size());
meshAppRuleListener.unregister(standardMeshRuleRouter2);
Assertions.assertEquals(
0, meshAppRuleListener.getMeshRuleDispatcher().getListenerMap().size());
}
@Test
void process() {
MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener("demo-route");
StandardMeshRuleRouter standardMeshRuleRouter = Mockito.spy(new StandardMeshRuleRouter(URL.valueOf("")));
meshAppRuleListener.register(standardMeshRuleRouter);
ConfigChangedEvent configChangedEvent = new ConfigChangedEvent(
"demo-route" + MESH_RULE_DATA_ID_SUFFIX,
DynamicConfiguration.DEFAULT_GROUP,
rule1 + "---\n" + rule2,
ConfigChangeType.ADDED);
meshAppRuleListener.process(configChangedEvent);
ArgumentCaptor<String> appCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<List<Map<String, Object>>> ruleCaptor = ArgumentCaptor.forClass(List.class);
verify(standardMeshRuleRouter, times(1)).onRuleChange(appCaptor.capture(), ruleCaptor.capture());
List<Map<String, Object>> rulesReceived = ruleCaptor.getValue();
assertEquals(2, rulesReceived.size());
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule1)));
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule2)));
configChangedEvent = new ConfigChangedEvent(
"demo-route" + MESH_RULE_DATA_ID_SUFFIX,
DynamicConfiguration.DEFAULT_GROUP,
rule1 + "---\n" + rule2,
ConfigChangeType.MODIFIED);
meshAppRuleListener.process(configChangedEvent);
verify(standardMeshRuleRouter, times(2)).onRuleChange(appCaptor.capture(), ruleCaptor.capture());
rulesReceived = ruleCaptor.getValue();
assertEquals(2, rulesReceived.size());
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule1)));
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule2)));
configChangedEvent = new ConfigChangedEvent(
"demo-route" + MESH_RULE_DATA_ID_SUFFIX,
DynamicConfiguration.DEFAULT_GROUP,
"",
ConfigChangeType.DELETED);
meshAppRuleListener.process(configChangedEvent);
verify(standardMeshRuleRouter, times(1)).clearRule("demo-route");
}
@Test
void testUnknownRule() {
MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener("demo-route");
StandardMeshRuleRouter standardMeshRuleRouter = Mockito.spy(new StandardMeshRuleRouter(URL.valueOf("")));
meshAppRuleListener.register(standardMeshRuleRouter);
meshAppRuleListener.receiveConfigInfo(rule3 + "---\n" + rule2);
ArgumentCaptor<String> appCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<List<Map<String, Object>>> ruleCaptor = ArgumentCaptor.forClass(List.class);
verify(standardMeshRuleRouter, times(1)).onRuleChange(appCaptor.capture(), ruleCaptor.capture());
List<Map<String, Object>> rulesReceived = ruleCaptor.getValue();
assertEquals(1, rulesReceived.size());
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule2)));
meshAppRuleListener.receiveConfigInfo(rule1 + "---\n" + rule4);
verify(standardMeshRuleRouter, times(2)).onRuleChange(appCaptor.capture(), ruleCaptor.capture());
rulesReceived = ruleCaptor.getValue();
assertEquals(1, rulesReceived.size());
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule1)));
meshAppRuleListener.receiveConfigInfo(rule3 + "---\n" + rule4);
verify(standardMeshRuleRouter, times(1)).clearRule("demo-route");
}
@Test
void testMultipleRule() {
MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener("demo-route");
AtomicInteger count = new AtomicInteger(0);
MeshRuleListener listener1 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
Assertions.assertEquals("demo-route", appName);
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
Assertions.assertTrue(rules.contains(yaml.load(rule5)));
Assertions.assertTrue(rules.contains(yaml.load(rule6)));
count.incrementAndGet();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type1";
}
};
MeshRuleListener listener2 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
Assertions.assertEquals("demo-route", appName);
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
Assertions.assertTrue(rules.contains(yaml.load(rule7)));
Assertions.assertTrue(rules.contains(yaml.load(rule8)));
count.incrementAndGet();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type2";
}
};
MeshRuleListener listener4 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
Assertions.fail();
}
@Override
public void clearRule(String appName) {
Assertions.assertEquals("demo-route", appName);
count.incrementAndGet();
}
@Override
public String ruleSuffix() {
return "Type4";
}
};
StandardMeshRuleRouter standardMeshRuleRouter = Mockito.spy(new StandardMeshRuleRouter(URL.valueOf("")));
meshAppRuleListener.register(standardMeshRuleRouter);
meshAppRuleListener.register(listener1);
meshAppRuleListener.register(listener2);
meshAppRuleListener.register(listener4);
meshAppRuleListener.receiveConfigInfo(
rule1 + "---\n" + rule2 + "---\n" + rule5 + "---\n" + rule6 + "---\n" + rule7 + "---\n" + rule8);
ArgumentCaptor<String> appCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<List<Map<String, Object>>> ruleCaptor = ArgumentCaptor.forClass(List.class);
verify(standardMeshRuleRouter, times(1)).onRuleChange(appCaptor.capture(), ruleCaptor.capture());
List<Map<String, Object>> rulesReceived = ruleCaptor.getValue();
assertEquals(2, rulesReceived.size());
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule1)));
Assertions.assertTrue(rulesReceived.contains(yaml.load(rule2)));
Assertions.assertEquals("demo-route", appCaptor.getValue());
Assertions.assertEquals(3, count.get());
}
}

View File

@ -1,109 +0,0 @@
/*
* 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.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.state.BitList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class MeshRuleCacheTest {
private Invoker<Object> createInvoker(String app) {
URL url = URL.valueOf(
"dubbo://localhost/DemoInterface?" + (StringUtils.isEmpty(app) ? "" : "remote.application=" + app));
Invoker invoker = Mockito.mock(Invoker.class);
when(invoker.getUrl()).thenReturn(url);
return invoker;
}
@Test
void containMapKeyValue() {
URL url = mock(URL.class);
when(url.getOriginalServiceParameter("test", "key1")).thenReturn("value1");
when(url.getOriginalServiceParameter("test", "key2")).thenReturn("value2");
when(url.getOriginalServiceParameter("test", "key3")).thenReturn("value3");
when(url.getOriginalServiceParameter("test", "key4")).thenReturn("value4");
Map<String, String> originMap = new HashMap<>();
originMap.put("key1", "value1");
originMap.put("key2", "value2");
originMap.put("key3", "value3");
Map<String, String> inputMap = new HashMap<>();
inputMap.put("key1", "value1");
inputMap.put("key2", "value2");
assertTrue(MeshRuleCache.isLabelMatch(url, "test", inputMap));
inputMap.put("key4", "value4");
assertTrue(MeshRuleCache.isLabelMatch(url, "test", inputMap));
}
@Test
void testBuild() {
BitList<Invoker<Object>> invokers =
new BitList<>(Arrays.asList(createInvoker(""), createInvoker("unknown"), createInvoker("app1")));
Subset subset = new Subset();
subset.setName("TestSubset");
DestinationRule destinationRule = new DestinationRule();
DestinationRuleSpec destinationRuleSpec = new DestinationRuleSpec();
destinationRuleSpec.setSubsets(Collections.singletonList(subset));
destinationRule.setSpec(destinationRuleSpec);
VsDestinationGroup vsDestinationGroup = new VsDestinationGroup();
vsDestinationGroup.getDestinationRuleList().add(destinationRule);
Map<String, VsDestinationGroup> vsDestinationGroupMap = new HashMap<>();
vsDestinationGroupMap.put("app1", vsDestinationGroup);
MeshRuleCache<Object> cache = MeshRuleCache.build("test", invokers, vsDestinationGroupMap);
assertEquals(2, cache.getUnmatchedInvokers().size());
assertEquals(1, cache.getSubsetInvokers("app1", "TestSubset").size());
subset.setLabels(Collections.singletonMap("test", "test"));
cache = MeshRuleCache.build("test", invokers, vsDestinationGroupMap);
assertEquals(3, cache.getUnmatchedInvokers().size());
assertEquals(0, cache.getSubsetInvokers("app1", "TestSubset").size());
invokers = new BitList<>(Arrays.asList(
createInvoker(""), createInvoker("unknown"), createInvoker("app1"), createInvoker("app2")));
subset.setLabels(null);
cache = MeshRuleCache.build("test", invokers, vsDestinationGroupMap);
assertEquals(3, cache.getUnmatchedInvokers().size());
assertEquals(1, cache.getSubsetInvokers("app1", "TestSubset").size());
assertEquals(0, cache.getSubsetInvokers("app2", "TestSubset").size());
}
}

View File

@ -1,273 +0,0 @@
/*
* 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.extension.ExtensionLoader;
import org.apache.dubbo.rpc.cluster.governance.GovernanceRuleRepository;
import org.apache.dubbo.rpc.cluster.router.mesh.util.MeshRuleListener;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
class MeshRuleManagerTest {
private static final String rule1 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: DestinationRule\n"
+ "metadata: { name: demo-route.Type1 }\n"
+ "spec:\n"
+ " host: demo\n"
+ "\n";
private static final String rule2 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: VirtualService\n"
+ "metadata: { name: demo-route.Type1 }\n"
+ "spec:\n"
+ " hosts: [demo]\n";
private static final String rule3 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: DestinationRule\n"
+ "metadata: { name: demo-route.Type2 }\n"
+ "spec:\n"
+ " host: demo\n"
+ "\n";
private static final String rule4 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: VirtualService\n"
+ "metadata: { name: demo-route.Type2 }\n"
+ "spec:\n"
+ " hosts: [demo]\n";
private ModuleModel originModule;
private ModuleModel moduleModel;
private GovernanceRuleRepository ruleRepository;
private Set<MeshEnvListenerFactory> envListenerFactories;
@BeforeEach
public void setup() {
originModule = ApplicationModel.defaultModel().getDefaultModule();
moduleModel = Mockito.spy(originModule);
ruleRepository = Mockito.mock(GovernanceRuleRepository.class);
when(moduleModel.getDefaultExtension(GovernanceRuleRepository.class)).thenReturn(ruleRepository);
ExtensionLoader<MeshEnvListenerFactory> envListenerFactoryLoader = Mockito.mock(ExtensionLoader.class);
envListenerFactories = new HashSet<>();
when(envListenerFactoryLoader.getSupportedExtensionInstances()).thenReturn(envListenerFactories);
when(moduleModel.getExtensionLoader(MeshEnvListenerFactory.class)).thenReturn(envListenerFactoryLoader);
}
@AfterEach
public void teardown() {
originModule.destroy();
}
@Test
void testRegister1() {
MeshRuleManager meshRuleManager = new MeshRuleManager(moduleModel);
MeshRuleListener meshRuleListener1 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
fail();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type1";
}
};
meshRuleManager.register("dubbo-demo", meshRuleListener1);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
verify(ruleRepository, times(1)).getRule("dubbo-demo.MESHAPPRULE", "dubbo", 5000L);
MeshAppRuleListener meshAppRuleListener =
meshRuleManager.getAppRuleListeners().values().iterator().next();
verify(ruleRepository, times(1)).addListener("dubbo-demo.MESHAPPRULE", "dubbo", meshAppRuleListener);
meshRuleManager.register("dubbo-demo", meshRuleListener1);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
MeshRuleListener meshRuleListener2 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
fail();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type2";
}
};
meshRuleManager.register("dubbo-demo", meshRuleListener2);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
assertEquals(
2, meshAppRuleListener.getMeshRuleDispatcher().getListenerMap().size());
meshRuleManager.unregister("dubbo-demo", meshRuleListener1);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
assertEquals(
1, meshAppRuleListener.getMeshRuleDispatcher().getListenerMap().size());
meshRuleManager.unregister("dubbo-demo", meshRuleListener2);
assertEquals(0, meshRuleManager.getAppRuleListeners().size());
verify(ruleRepository, times(1)).removeListener("dubbo-demo.MESHAPPRULE", "dubbo", meshAppRuleListener);
}
@Test
void testRegister2() {
MeshRuleManager meshRuleManager = new MeshRuleManager(moduleModel);
AtomicInteger invokeTimes = new AtomicInteger(0);
MeshRuleListener meshRuleListener = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
assertEquals("dubbo-demo", appName);
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
assertTrue(rules.contains(yaml.load(rule1)));
assertTrue(rules.contains(yaml.load(rule2)));
invokeTimes.incrementAndGet();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type1";
}
};
when(ruleRepository.getRule("dubbo-demo.MESHAPPRULE", "dubbo", 5000L)).thenReturn(rule1 + "---\n" + rule2);
meshRuleManager.register("dubbo-demo", meshRuleListener);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
verify(ruleRepository, times(1)).getRule("dubbo-demo.MESHAPPRULE", "dubbo", 5000L);
verify(ruleRepository, times(1))
.addListener(
"dubbo-demo.MESHAPPRULE",
"dubbo",
meshRuleManager
.getAppRuleListeners()
.values()
.iterator()
.next());
assertEquals(1, invokeTimes.get());
meshRuleManager.register("dubbo-demo", meshRuleListener);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
}
@Test
void testRegister3() {
MeshEnvListenerFactory meshEnvListenerFactory1 = Mockito.mock(MeshEnvListenerFactory.class);
MeshEnvListenerFactory meshEnvListenerFactory2 = Mockito.mock(MeshEnvListenerFactory.class);
MeshEnvListener meshEnvListener1 = Mockito.mock(MeshEnvListener.class);
when(meshEnvListenerFactory1.getListener()).thenReturn(meshEnvListener1);
MeshEnvListener meshEnvListener2 = Mockito.mock(MeshEnvListener.class);
when(meshEnvListenerFactory2.getListener()).thenReturn(meshEnvListener2);
envListenerFactories.add(meshEnvListenerFactory1);
envListenerFactories.add(meshEnvListenerFactory2);
MeshRuleManager meshRuleManager = new MeshRuleManager(moduleModel);
MeshRuleListener meshRuleListener1 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
fail();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type1";
}
};
when(meshEnvListener1.isEnable()).thenReturn(false);
when(meshEnvListener2.isEnable()).thenReturn(true);
meshRuleManager.register("dubbo-demo", meshRuleListener1);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
verify(ruleRepository, times(1)).getRule("dubbo-demo.MESHAPPRULE", "dubbo", 5000L);
MeshAppRuleListener meshAppRuleListener =
meshRuleManager.getAppRuleListeners().values().iterator().next();
verify(ruleRepository, times(1)).addListener("dubbo-demo.MESHAPPRULE", "dubbo", meshAppRuleListener);
verify(meshEnvListener2, times(1)).onSubscribe("dubbo-demo", meshAppRuleListener);
meshRuleManager.register("dubbo-demo", meshRuleListener1);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
MeshRuleListener meshRuleListener2 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
fail();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type2";
}
};
meshRuleManager.register("dubbo-demo", meshRuleListener2);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
assertEquals(
2, meshAppRuleListener.getMeshRuleDispatcher().getListenerMap().size());
meshRuleManager.unregister("dubbo-demo", meshRuleListener1);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
assertEquals(
1, meshAppRuleListener.getMeshRuleDispatcher().getListenerMap().size());
meshRuleManager.unregister("dubbo-demo", meshRuleListener2);
assertEquals(0, meshRuleManager.getAppRuleListeners().size());
verify(ruleRepository, times(1)).removeListener("dubbo-demo.MESHAPPRULE", "dubbo", meshAppRuleListener);
verify(meshEnvListener2, times(1)).onUnSubscribe("dubbo-demo");
}
}

View File

@ -1,455 +0,0 @@
/*
* 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.beans.factory.ScopeBeanFactory;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.utils.Holder;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.cluster.router.mesh.util.TracingContextProvider;
import org.apache.dubbo.rpc.cluster.router.state.BitList;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
class MeshRuleRouterTest {
private static final String rule1 = "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";
private static final String rule2 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: VirtualService\n"
+ "metadata: { name: demo-route }\n"
+ "spec:\n"
+ " dubbo:\n"
+ " - routedetail:\n"
+ " - match:\n"
+ " - attachments: \n"
+ " dubboContext: {trafficLabel: {regex: xxx}}\n"
+ " name: xxx-project\n"
+ " route:\n"
+ " - destination: {host: demo, subset: isolation}\n"
+ " - match:\n"
+ " - attachments: \n"
+ " dubboContext: {trafficLabel: {regex: testing-trunk}}\n"
+ " name: testing-trunk\n"
+ " route:\n"
+ " - destination:\n"
+ " host: demo\n"
+ " subset: testing-trunk\n"
+ " fallback:\n"
+ " host: demo\n"
+ " subset: testing\n"
+ " - name: testing\n"
+ " route:\n"
+ " - destination: {host: demo, subset: testing}\n"
+ " services:\n"
+ " - {regex: ccc}\n"
+ " hosts: [demo]\n";
private static final String rule3 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: VirtualService\n"
+ "metadata: { name: demo-route }\n"
+ "spec:\n"
+ " dubbo:\n"
+ " - routedetail:\n"
+ " - match:\n"
+ " - attachments: \n"
+ " dubboContext: {trafficLabel: {regex: xxx}}\n"
+ " name: xxx-project\n"
+ " route:\n"
+ " - destination: {host: demo, subset: isolation}\n"
+ " - match:\n"
+ " - attachments: \n"
+ " dubboContext: {trafficLabel: {regex: testing-trunk}}\n"
+ " name: testing-trunk\n"
+ " route:\n"
+ " - destination:\n"
+ " host: demo\n"
+ " subset: testing-trunk\n"
+ " fallback:\n"
+ " host: demo\n"
+ " subset: testing\n"
+ " - match:\n"
+ " - attachments: \n"
+ " dubboContext: {trafficLabel: {regex: testing}}\n"
+ " name: testing\n"
+ " route:\n"
+ " - destination: {host: demo, subset: testing}\n"
+ " hosts: [demo]\n";
private static final String rule4 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: VirtualService\n"
+ "metadata: { name: demo-route }\n"
+ "spec:\n"
+ " dubbo:\n"
+ " - routedetail:\n"
+ " - match:\n"
+ " - attachments: \n"
+ " dubboContext: {trafficLabel: {regex: xxx}}\n"
+ " name: xxx-project\n"
+ " route:\n"
+ " - destination: {host: demo, subset: isolation}\n"
+ " - match:\n"
+ " - attachments: \n"
+ " dubboContext: {trafficLabel: {regex: testing-trunk}}\n"
+ " name: testing-trunk\n"
+ " route:\n"
+ " - destination:\n"
+ " host: demo\n"
+ " subset: testing-trunk\n"
+ " fallback:\n"
+ " destination:\n"
+ " host: demo\n"
+ " subset: testing\n"
+ " - weight: 10\n"
+ " destination:\n"
+ " host: demo\n"
+ " subset: isolation\n"
+ " - match:\n"
+ " - attachments: \n"
+ " dubboContext: {trafficLabel: {regex: testing}}\n"
+ " name: testing\n"
+ " route:\n"
+ " - destination: {host: demo, subset: testing}\n"
+ " hosts: [demo]\n";
private ModuleModel originModel;
private ModuleModel moduleModel;
private MeshRuleManager meshRuleManager;
private Set<TracingContextProvider> tracingContextProviders;
private URL url;
@BeforeEach
public void setup() {
originModel = ApplicationModel.defaultModel().getDefaultModule();
moduleModel = Mockito.spy(originModel);
ScopeBeanFactory originBeanFactory = originModel.getBeanFactory();
ScopeBeanFactory beanFactory = Mockito.spy(originBeanFactory);
when(moduleModel.getBeanFactory()).thenReturn(beanFactory);
meshRuleManager = Mockito.mock(MeshRuleManager.class);
when(beanFactory.getBean(MeshRuleManager.class)).thenReturn(meshRuleManager);
ExtensionLoader<TracingContextProvider> extensionLoader = Mockito.mock(ExtensionLoader.class);
tracingContextProviders = new HashSet<>();
when(extensionLoader.getSupportedExtensionInstances()).thenReturn(tracingContextProviders);
when(moduleModel.getExtensionLoader(TracingContextProvider.class)).thenReturn(extensionLoader);
url = URL.valueOf("test://localhost/DemoInterface").setScopeModel(moduleModel);
}
@AfterEach
public void teardown() {
originModel.destroy();
}
private Invoker<Object> createInvoker(String app) {
URL url = URL.valueOf(
"dubbo://localhost/DemoInterface?" + (StringUtils.isEmpty(app) ? "" : "remote.application=" + app));
Invoker invoker = Mockito.mock(Invoker.class);
when(invoker.getUrl()).thenReturn(url);
return invoker;
}
private Invoker<Object> createInvoker(Map<String, String> parameters) {
URL url = URL.valueOf("dubbo://localhost/DemoInterface?remote.application=app1")
.addParameters(parameters);
Invoker invoker = Mockito.mock(Invoker.class);
when(invoker.getUrl()).thenReturn(url);
return invoker;
}
@Test
void testNotify() {
StandardMeshRuleRouter<Object> meshRuleRouter = new StandardMeshRuleRouter<>(url);
meshRuleRouter.notify(null);
assertEquals(0, meshRuleRouter.getRemoteAppName().size());
BitList<Invoker<Object>> invokers =
new BitList<>(Arrays.asList(createInvoker(""), createInvoker("unknown"), createInvoker("app1")));
meshRuleRouter.notify(invokers);
assertEquals(1, meshRuleRouter.getRemoteAppName().size());
assertTrue(meshRuleRouter.getRemoteAppName().contains("app1"));
assertEquals(invokers, meshRuleRouter.getInvokerList());
verify(meshRuleManager, times(1)).register("app1", meshRuleRouter);
invokers = new BitList<>(Arrays.asList(createInvoker("unknown"), createInvoker("app2")));
meshRuleRouter.notify(invokers);
verify(meshRuleManager, times(1)).register("app2", meshRuleRouter);
verify(meshRuleManager, times(1)).unregister("app1", meshRuleRouter);
assertEquals(invokers, meshRuleRouter.getInvokerList());
meshRuleRouter.stop();
verify(meshRuleManager, times(1)).unregister("app2", meshRuleRouter);
}
@Test
void testRuleChange() {
StandardMeshRuleRouter<Object> meshRuleRouter = new StandardMeshRuleRouter<>(url);
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
List<Map<String, Object>> rules = new LinkedList<>();
rules.add(yaml.load(rule1));
meshRuleRouter.onRuleChange("app1", rules);
assertEquals(0, meshRuleRouter.getMeshRuleCache().getAppToVDGroup().size());
rules.add(yaml.load(rule2));
meshRuleRouter.onRuleChange("app1", rules);
assertEquals(1, meshRuleRouter.getMeshRuleCache().getAppToVDGroup().size());
assertTrue(meshRuleRouter.getMeshRuleCache().getAppToVDGroup().containsKey("app1"));
meshRuleRouter.onRuleChange("app2", rules);
assertEquals(2, meshRuleRouter.getMeshRuleCache().getAppToVDGroup().size());
assertTrue(meshRuleRouter.getMeshRuleCache().getAppToVDGroup().containsKey("app1"));
assertTrue(meshRuleRouter.getMeshRuleCache().getAppToVDGroup().containsKey("app2"));
meshRuleRouter.clearRule("app1");
assertEquals(1, meshRuleRouter.getMeshRuleCache().getAppToVDGroup().size());
assertTrue(meshRuleRouter.getMeshRuleCache().getAppToVDGroup().containsKey("app2"));
}
@Test
void testRoute1() {
StandardMeshRuleRouter<Object> meshRuleRouter = new StandardMeshRuleRouter<>(url);
BitList<Invoker<Object>> invokers =
new BitList<>(Arrays.asList(createInvoker(""), createInvoker("unknown"), createInvoker("app1")));
assertEquals(invokers, meshRuleRouter.route(invokers.clone(), null, null, false, null));
Holder<String> message = new Holder<>();
meshRuleRouter.doRoute(invokers.clone(), null, null, true, null, message);
assertEquals("MeshRuleCache has not been built. Skip route.", message.get());
}
@Test
void testRoute2() {
StandardMeshRuleRouter<Object> meshRuleRouter = new StandardMeshRuleRouter<>(url);
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
List<Map<String, Object>> rules = new LinkedList<>();
rules.add(yaml.load(rule1));
rules.add(yaml.load(rule2));
meshRuleRouter.onRuleChange("app1", rules);
Invoker<Object> isolation = createInvoker(new HashMap<String, String>() {
{
put("env-sign", "xxx");
put("tag1", "hello");
}
});
Invoker<Object> testingTrunk = createInvoker(Collections.singletonMap("env-sign", "yyy"));
Invoker<Object> testing = createInvoker(Collections.singletonMap("env-sign", "zzz"));
BitList<Invoker<Object>> invokers = new BitList<>(Arrays.asList(isolation, testingTrunk, testing));
meshRuleRouter.notify(invokers);
RpcInvocation rpcInvocation = new RpcInvocation();
rpcInvocation.setServiceName("ccc");
rpcInvocation.setAttachment("trafficLabel", "xxx");
assertEquals(
1,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.size());
assertEquals(
isolation,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.get(0));
Holder<String> message = new Holder<>();
meshRuleRouter.doRoute(invokers.clone(), null, rpcInvocation, true, null, message);
assertEquals("Match App: app1 Subset: isolation ", message.get());
rpcInvocation.setAttachment("trafficLabel", "testing-trunk");
assertEquals(
1,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.size());
assertEquals(
testingTrunk,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.get(0));
rpcInvocation.setAttachment("trafficLabel", null);
assertEquals(
1,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.size());
assertEquals(
testing,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.get(0));
rpcInvocation.setServiceName("aaa");
assertEquals(invokers, meshRuleRouter.route(invokers.clone(), null, rpcInvocation, false, null));
message = new Holder<>();
meshRuleRouter.doRoute(invokers.clone(), null, rpcInvocation, true, null, message);
assertEquals("Empty protection after routed.", message.get());
rules = new LinkedList<>();
rules.add(yaml.load(rule1));
rules.add(yaml.load(rule3));
meshRuleRouter.onRuleChange("app1", rules);
rpcInvocation.setServiceName("ccc");
rpcInvocation.setAttachment("trafficLabel", "xxx");
assertEquals(
1,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.size());
assertEquals(
isolation,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.get(0));
rpcInvocation.setAttachment("trafficLabel", "testing-trunk");
assertEquals(
1,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.size());
assertEquals(
testingTrunk,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.get(0));
rpcInvocation.setAttachment("trafficLabel", "testing");
assertEquals(
1,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.size());
assertEquals(
testing,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.get(0));
rpcInvocation.setServiceName("aaa");
assertEquals(
1,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.size());
assertEquals(
testing,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.get(0));
rpcInvocation.setAttachment("trafficLabel", null);
assertEquals(invokers, meshRuleRouter.route(invokers.clone(), null, rpcInvocation, false, null));
rules = new LinkedList<>();
rules.add(yaml.load(rule1));
rules.add(yaml.load(rule4));
meshRuleRouter.onRuleChange("app1", rules);
rpcInvocation.setAttachment("trafficLabel", "testing-trunk");
int testingCount = 0;
int isolationCount = 0;
for (int i = 0; i < 1000; i++) {
BitList<Invoker<Object>> result = meshRuleRouter.route(invokers.clone(), null, rpcInvocation, false, null);
assertEquals(1, result.size());
if (result.contains(testing)) {
testingCount++;
} else {
isolationCount++;
}
}
assertTrue(isolationCount > testingCount * 10);
invokers.removeAll(Arrays.asList(isolation, testingTrunk));
for (int i = 0; i < 1000; i++) {
assertEquals(
1,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.size());
assertEquals(
testing,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.get(0));
}
meshRuleRouter.notify(invokers);
for (int i = 0; i < 1000; i++) {
assertEquals(
1,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.size());
assertEquals(
testing,
meshRuleRouter
.route(invokers.clone(), null, rpcInvocation, false, null)
.get(0));
}
Invoker<Object> mock = createInvoker(Collections.singletonMap("env-sign", "mock"));
invokers = new BitList<>(Arrays.asList(isolation, testingTrunk, testing, mock));
meshRuleRouter.notify(invokers);
invokers.removeAll(Arrays.asList(isolation, testingTrunk, testing));
assertEquals(invokers, meshRuleRouter.route(invokers.clone(), null, rpcInvocation, false, null));
}
}

View File

@ -1,32 +0,0 @@
/*
* 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.Assertions;
import org.junit.jupiter.api.Test;
class StandardMeshRuleRouterFactoryTest {
@Test
void getRouter() {
StandardMeshRuleRouterFactory ruleRouterFactory = new StandardMeshRuleRouterFactory();
Assertions.assertTrue(
ruleRouterFactory.getRouter(Object.class, URL.valueOf("")) instanceof StandardMeshRuleRouter);
}
}

View File

@ -1,114 +0,0 @@
/*
* 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 java.util.Map;
import org.junit.jupiter.api.Test;
import org.yaml.snakeyaml.Yaml;
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.DESTINATION_RULE_KEY;
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.KIND_KEY;
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.VIRTUAL_SERVICE_KEY;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class DestinationRuleTest {
@Test
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(DESTINATION_RULE_KEY, 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
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(DESTINATION_RULE_KEY)) {
DestinationRule destinationRule = yaml2.loadAs(yaml2.dump(result), DestinationRule.class);
System.out.println(destinationRule);
assertNotNull(destinationRule);
} else if (resultMap.get(KIND_KEY).equals(VIRTUAL_SERVICE_KEY)) {
VirtualServiceRule virtualServiceRule = yaml2.loadAs(yaml2.dump(result), VirtualServiceRule.class);
System.out.println(virtualServiceRule);
assertNotNull(virtualServiceRule);
}
}
}
}

View File

@ -1,94 +0,0 @@
/*
* 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.DubboRoute;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.DubboRouteDetail;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceRule;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.yaml.snakeyaml.Yaml;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
class VirtualServiceRuleTest {
@Test
void parserTest() {
Yaml yaml = new Yaml();
VirtualServiceRule virtualServiceRule = yaml.loadAs(
this.getClass().getClassLoader().getResourceAsStream("VirtualServiceTest.yaml"),
VirtualServiceRule.class);
System.out.println(virtualServiceRule);
assertNotNull(virtualServiceRule);
assertEquals("service.dubbo.apache.org/v1alpha1", virtualServiceRule.getApiVersion());
assertEquals("VirtualService", virtualServiceRule.getKind());
assertEquals("demo-route", virtualServiceRule.getMetadata().get("name"));
List<String> hosts = virtualServiceRule.getSpec().getHosts();
assertEquals(1, hosts.size());
assertEquals("demo", hosts.get(0));
List<DubboRoute> dubboRoutes = virtualServiceRule.getSpec().getDubbo();
assertEquals(1, dubboRoutes.size());
DubboRoute dubboRoute = dubboRoutes.get(0);
assertNull(dubboRoute.getName());
assertEquals(1, dubboRoute.getServices().size());
assertEquals("ccc", dubboRoute.getServices().get(0).getRegex());
List<DubboRouteDetail> routedetail = dubboRoute.getRoutedetail();
DubboRouteDetail firstDubboRouteDetail = routedetail.get(0);
DubboRouteDetail secondDubboRouteDetail = routedetail.get(1);
DubboRouteDetail thirdDubboRouteDetail = routedetail.get(2);
assertEquals("xxx-project", firstDubboRouteDetail.getName());
assertEquals(
"xxx", firstDubboRouteDetail.getMatch().get(0).getSourceLabels().get("trafficLabel"));
assertEquals(
"demo", firstDubboRouteDetail.getRoute().get(0).getDestination().getHost());
assertEquals(
"isolation",
firstDubboRouteDetail.getRoute().get(0).getDestination().getSubset());
assertEquals("testing-trunk", secondDubboRouteDetail.getName());
assertEquals(
"testing-trunk",
secondDubboRouteDetail.getMatch().get(0).getSourceLabels().get("trafficLabel"));
assertEquals(
"demo",
secondDubboRouteDetail.getRoute().get(0).getDestination().getHost());
assertEquals(
"testing-trunk",
secondDubboRouteDetail.getRoute().get(0).getDestination().getSubset());
assertEquals("testing", thirdDubboRouteDetail.getName());
assertNull(thirdDubboRouteDetail.getMatch());
assertEquals(
"demo", thirdDubboRouteDetail.getRoute().get(0).getDestination().getHost());
assertEquals(
"testing",
thirdDubboRouteDetail.getRoute().get(0).getDestination().getSubset());
}
}

View File

@ -1,135 +0,0 @@
/*
* 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.RpcInvocation;
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.apache.dubbo.rpc.cluster.router.mesh.util.TracingContextProvider;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class DubboMatchRequestTest {
@Test
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);
RpcInvocation rpcInvocation = new RpcInvocation();
rpcInvocation.setMethodName("sayHello");
assertTrue(dubboMatchRequest.isMatch(rpcInvocation, new HashMap<>(), Collections.emptySet()));
rpcInvocation.setMethodName("satHi");
assertFalse(dubboMatchRequest.isMatch(rpcInvocation, new HashMap<>(), Collections.emptySet()));
// sourceLabels
Map<String, String> sourceLabels = new HashMap<>();
sourceLabels.put("key1", "value1");
sourceLabels.put("key2", "value2");
dubboMatchRequest.setSourceLabels(sourceLabels);
Map<String, String> inputSourceLabelsMap = new HashMap<>();
inputSourceLabelsMap.put("key1", "value1");
inputSourceLabelsMap.put("key2", "value2");
inputSourceLabelsMap.put("key3", "value3");
Map<String, String> inputSourceLabelsMap2 = new HashMap<>();
inputSourceLabelsMap2.put("key1", "other");
inputSourceLabelsMap2.put("key2", "value2");
inputSourceLabelsMap2.put("key3", "value3");
rpcInvocation.setMethodName("sayHello");
assertTrue(dubboMatchRequest.isMatch(rpcInvocation, inputSourceLabelsMap, Collections.emptySet()));
assertFalse(dubboMatchRequest.isMatch(rpcInvocation, inputSourceLabelsMap2, Collections.emptySet()));
// tracingContext
DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
Map<String, StringMatch> tracingContextMatchMap = new HashMap<>();
StringMatch nameMatch = new StringMatch();
nameMatch.setExact("qinliujie");
tracingContextMatchMap.put("name", nameMatch);
dubboAttachmentMatch.setTracingContext(tracingContextMatchMap);
dubboMatchRequest.setAttachments(dubboAttachmentMatch);
Map<String, String> invokeTracingContextMap = new HashMap<>();
invokeTracingContextMap.put("name", "qinliujie");
invokeTracingContextMap.put("machineGroup", "test_host");
invokeTracingContextMap.put("other", "other");
TracingContextProvider tracingContextProvider = (invocation, key) -> invokeTracingContextMap.get(key);
assertTrue(dubboMatchRequest.isMatch(
rpcInvocation, inputSourceLabelsMap, Collections.singleton(tracingContextProvider)));
Map<String, String> invokeTracingContextMap2 = new HashMap<>();
invokeTracingContextMap2.put("name", "jack");
invokeTracingContextMap2.put("machineGroup", "test_host");
invokeTracingContextMap2.put("other", "other");
TracingContextProvider tracingContextProvider2 = (invocation, key) -> invokeTracingContextMap2.get(key);
assertFalse(dubboMatchRequest.isMatch(
rpcInvocation, inputSourceLabelsMap, Collections.singleton(tracingContextProvider2)));
// dubbo context
dubboAttachmentMatch = new DubboAttachmentMatch();
Map<String, StringMatch> eagleeyecontextMatchMap = new HashMap<>();
nameMatch = new StringMatch();
nameMatch.setExact("qinliujie");
eagleeyecontextMatchMap.put("name", nameMatch);
dubboAttachmentMatch.setTracingContext(eagleeyecontextMatchMap);
Map<String, StringMatch> dubboContextMatchMap = new HashMap<>();
StringMatch dpathMatch = new StringMatch();
dpathMatch.setExact("PRE");
dubboContextMatchMap.put("dpath", dpathMatch);
dubboAttachmentMatch.setDubboContext(dubboContextMatchMap);
dubboMatchRequest.setAttachments(dubboAttachmentMatch);
Map<String, String> invokeDubboContextMap = new HashMap<>();
invokeDubboContextMap.put("dpath", "PRE");
rpcInvocation.setAttachments(invokeDubboContextMap);
TracingContextProvider tracingContextProvider3 = (invocation, key) -> invokeTracingContextMap.get(key);
assertTrue(dubboMatchRequest.isMatch(
rpcInvocation, inputSourceLabelsMap, Collections.singleton(tracingContextProvider3)));
Map<String, String> invokeDubboContextMap2 = new HashMap<>();
invokeDubboContextMap.put("dpath", "other");
rpcInvocation.setAttachments(invokeDubboContextMap2);
assertFalse(dubboMatchRequest.isMatch(
rpcInvocation, inputSourceLabelsMap, Collections.singleton(tracingContextProvider3)));
}
}

View File

@ -1,38 +0,0 @@
/*
* 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;
class BoolMatchTest {
@Test
void isMatch() {
BoolMatch boolMatch = new BoolMatch();
boolMatch.setExact(true);
assertTrue(boolMatch.isMatch(true));
assertFalse(boolMatch.isMatch(false));
boolMatch.setExact(false);
assertFalse(boolMatch.isMatch(true));
assertTrue(boolMatch.isMatch(false));
}
}

View File

@ -1,95 +0,0 @@
/*
* 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;
class DoubleMatchTest {
@Test
void exactMatch() {
DoubleMatch doubleMatch = new DoubleMatch();
doubleMatch.setExact(10.0);
assertTrue(doubleMatch.isMatch(10.0));
assertFalse(doubleMatch.isMatch(9.0));
}
@Test
void rangeStartMatch() {
DoubleMatch doubleMatch = new DoubleMatch();
DoubleRangeMatch doubleRangeMatch = new DoubleRangeMatch();
doubleRangeMatch.setStart(10.0);
doubleMatch.setRange(doubleRangeMatch);
assertTrue(doubleMatch.isMatch(10.0));
assertFalse(doubleMatch.isMatch(9.0));
}
@Test
void rangeEndMatch() {
DoubleMatch doubleMatch = new DoubleMatch();
DoubleRangeMatch doubleRangeMatch = new DoubleRangeMatch();
doubleRangeMatch.setEnd(10.0);
doubleMatch.setRange(doubleRangeMatch);
assertFalse(doubleMatch.isMatch(10.0));
assertTrue(doubleMatch.isMatch(9.0));
}
@Test
void rangeStartEndMatch() {
DoubleMatch doubleMatch = new DoubleMatch();
DoubleRangeMatch doubleRangeMatch = new DoubleRangeMatch();
doubleRangeMatch.setStart(5.0);
doubleRangeMatch.setEnd(10.0);
doubleMatch.setRange(doubleRangeMatch);
assertTrue(doubleMatch.isMatch(5.0));
assertFalse(doubleMatch.isMatch(10.0));
assertFalse(doubleMatch.isMatch(4.9));
assertFalse(doubleMatch.isMatch(10.1));
assertTrue(doubleMatch.isMatch(6.0));
}
@Test
void modMatch() {
DoubleMatch doubleMatch = new DoubleMatch();
doubleMatch.setMod(2.0);
doubleMatch.setExact(3.0);
assertFalse(doubleMatch.isMatch(3.0));
doubleMatch.setExact(1.0);
assertTrue(doubleMatch.isMatch(1.0));
assertFalse(doubleMatch.isMatch(2.0));
assertTrue(doubleMatch.isMatch(3.0));
}
}

View File

@ -1,198 +0,0 @@
/*
* 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.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.cluster.router.mesh.util.TracingContextProvider;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class DubboAttachmentMatchTest {
@Test
void dubboContextMatch() {
DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
Map<String, StringMatch> dubbocontextMatchMap = new HashMap<>();
StringMatch nameMatch = new StringMatch();
nameMatch.setExact("qinliujie");
dubbocontextMatchMap.put("name", nameMatch);
StringMatch machineGroupMatch = new StringMatch();
machineGroupMatch.setExact("test_host");
dubbocontextMatchMap.put("machineGroup", machineGroupMatch);
dubboAttachmentMatch.setDubboContext(dubbocontextMatchMap);
Map<String, String> invokeDubboContextMap = new HashMap<>();
invokeDubboContextMap.put("name", "qinliujie");
invokeDubboContextMap.put("machineGroup", "test_host");
invokeDubboContextMap.put("other", "other");
RpcInvocation rpcInvocation = new RpcInvocation();
rpcInvocation.setAttachments(invokeDubboContextMap);
assertTrue(dubboAttachmentMatch.isMatch(rpcInvocation, Collections.emptySet()));
Map<String, String> invokeDubboContextMap2 = new HashMap<>();
invokeDubboContextMap2.put("name", "jack");
invokeDubboContextMap2.put("machineGroup", "test_host");
invokeDubboContextMap2.put("other", "other");
RpcInvocation rpcInvocation2 = new RpcInvocation();
rpcInvocation2.setAttachments(invokeDubboContextMap2);
assertFalse(dubboAttachmentMatch.isMatch(rpcInvocation2, Collections.emptySet()));
Map<String, String> invokeDubboContextMap3 = new HashMap<>();
invokeDubboContextMap3.put("name", "qinliujie");
invokeDubboContextMap3.put("machineGroup", "my_host");
invokeDubboContextMap3.put("other", "other");
RpcInvocation rpcInvocation3 = new RpcInvocation();
rpcInvocation3.setAttachments(invokeDubboContextMap3);
assertFalse(dubboAttachmentMatch.isMatch(rpcInvocation3, Collections.emptySet()));
}
@Test
void tracingContextMatch() {
DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
Map<String, StringMatch> tracingContextMatchMap = new HashMap<>();
StringMatch nameMatch = new StringMatch();
nameMatch.setExact("qinliujie");
tracingContextMatchMap.put("name", nameMatch);
StringMatch machineGroupMatch = new StringMatch();
machineGroupMatch.setExact("test_host");
tracingContextMatchMap.put("machineGroup", machineGroupMatch);
dubboAttachmentMatch.setTracingContext(tracingContextMatchMap);
Map<String, String> invokeEagleEyeContextMap = new HashMap<>();
invokeEagleEyeContextMap.put("name", "qinliujie");
invokeEagleEyeContextMap.put("machineGroup", "test_host");
invokeEagleEyeContextMap.put("other", "other");
TracingContextProvider tracingContextProvider = (invocation, key) -> invokeEagleEyeContextMap.get(key);
assertTrue(dubboAttachmentMatch.isMatch(
Mockito.mock(Invocation.class), Collections.singleton(tracingContextProvider)));
Map<String, String> invokeTracingContextMap2 = new HashMap<>();
invokeTracingContextMap2.put("name", "jack");
invokeTracingContextMap2.put("machineGroup", "test_host");
invokeTracingContextMap2.put("other", "other");
TracingContextProvider tracingContextProvider2 = (invocation, key) -> invokeTracingContextMap2.get(key);
assertFalse(dubboAttachmentMatch.isMatch(
Mockito.mock(Invocation.class), Collections.singleton(tracingContextProvider2)));
Map<String, String> invokeEagleEyeContextMap3 = new HashMap<>();
invokeEagleEyeContextMap3.put("name", "qinliujie");
invokeEagleEyeContextMap3.put("machineGroup", "my_host");
invokeEagleEyeContextMap3.put("other", "other");
TracingContextProvider tracingContextProvider3 = (invocation, key) -> invokeEagleEyeContextMap3.get(key);
assertFalse(dubboAttachmentMatch.isMatch(
Mockito.mock(Invocation.class), Collections.singleton(tracingContextProvider3)));
}
@Test
void contextMatch() {
DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
Map<String, StringMatch> tracingContextMatchMap = new HashMap<>();
StringMatch nameMatch = new StringMatch();
nameMatch.setExact("qinliujie");
tracingContextMatchMap.put("name", nameMatch);
dubboAttachmentMatch.setTracingContext(tracingContextMatchMap);
Map<String, String> invokeTracingContextMap = new HashMap<>();
invokeTracingContextMap.put("name", "qinliujie");
invokeTracingContextMap.put("machineGroup", "test_host");
invokeTracingContextMap.put("other", "other");
Map<String, StringMatch> dubboContextMatchMap = new HashMap<>();
StringMatch dpathMatch = new StringMatch();
dpathMatch.setExact("PRE");
dubboContextMatchMap.put("dpath", dpathMatch);
dubboAttachmentMatch.setDubboContext(dubboContextMatchMap);
Map<String, String> invokeDubboContextMap = new HashMap<>();
invokeDubboContextMap.put("dpath", "PRE");
TracingContextProvider tracingContextProvider = (invocation, key) -> invokeTracingContextMap.get(key);
RpcInvocation rpcInvocation = new RpcInvocation();
rpcInvocation.setAttachments(invokeDubboContextMap);
assertTrue(dubboAttachmentMatch.isMatch(rpcInvocation, Collections.singleton(tracingContextProvider)));
Map<String, String> invokeTracingContextMap1 = new HashMap<>();
invokeTracingContextMap1.put("name", "jack");
invokeTracingContextMap1.put("machineGroup", "test_host");
invokeTracingContextMap1.put("other", "other");
TracingContextProvider tracingContextProvider1 = (invocation, key) -> invokeTracingContextMap1.get(key);
RpcInvocation rpcInvocation1 = new RpcInvocation();
rpcInvocation1.setAttachments(invokeDubboContextMap);
assertFalse(dubboAttachmentMatch.isMatch(rpcInvocation1, Collections.singleton(tracingContextProvider1)));
Map<String, String> invokeDubboContextMap1 = new HashMap<>();
invokeDubboContextMap1.put("dpath", "PRE-2");
TracingContextProvider tracingContextProvider2 = (invocation, key) -> invokeTracingContextMap.get(key);
RpcInvocation rpcInvocation2 = new RpcInvocation();
rpcInvocation2.setAttachments(invokeDubboContextMap1);
assertFalse(dubboAttachmentMatch.isMatch(rpcInvocation2, Collections.singleton(tracingContextProvider2)));
TracingContextProvider tracingContextProvider3 = (invocation, key) -> invokeTracingContextMap1.get(key);
RpcInvocation rpcInvocation3 = new RpcInvocation();
rpcInvocation3.setAttachments(invokeDubboContextMap1);
assertFalse(dubboAttachmentMatch.isMatch(rpcInvocation3, Collections.singleton(tracingContextProvider3)));
Map<String, String> invokeTracingContextMap2 = new HashMap<>();
invokeTracingContextMap2.put("machineGroup", "test_host");
invokeTracingContextMap2.put("other", "other");
TracingContextProvider tracingContextProvider4 = (invocation, key) -> invokeTracingContextMap2.get(key);
RpcInvocation rpcInvocation4 = new RpcInvocation();
rpcInvocation4.setAttachments(invokeDubboContextMap);
assertFalse(dubboAttachmentMatch.isMatch(rpcInvocation4, Collections.singleton(tracingContextProvider4)));
Map<String, String> invokeDubboContextMap2 = new HashMap<>();
TracingContextProvider tracingContextProvider5 = (invocation, key) -> invokeTracingContextMap.get(key);
RpcInvocation rpcInvocation5 = new RpcInvocation();
rpcInvocation5.setAttachments(invokeDubboContextMap2);
assertFalse(dubboAttachmentMatch.isMatch(rpcInvocation5, Collections.singleton(tracingContextProvider5)));
TracingContextProvider tracingContextProvider6 = (invocation, key) -> invokeTracingContextMap2.get(key);
RpcInvocation rpcInvocation6 = new RpcInvocation();
rpcInvocation5.setAttachments(invokeDubboContextMap2);
assertFalse(dubboAttachmentMatch.isMatch(rpcInvocation6, Collections.singleton(tracingContextProvider6)));
}
}

View File

@ -1,159 +0,0 @@
/*
* 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.apache.dubbo.rpc.RpcInvocation;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class DubboMethodMatchTest {
@Test
void nameMatch() {
DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
StringMatch nameStringMatch = new StringMatch();
nameStringMatch.setExact("sayHello");
dubboMethodMatch.setName_match(nameStringMatch);
assertTrue(
dubboMethodMatch.isMatch(new RpcInvocation(null, "sayHello", "", "", new Class[] {}, new Object[] {})));
}
@Test
void argcMatch() {
DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
dubboMethodMatch.setArgc(1);
assertFalse(
dubboMethodMatch.isMatch(new RpcInvocation(null, "sayHello", "", "", new Class[] {}, new Object[] {})));
assertTrue(dubboMethodMatch.isMatch(
new RpcInvocation(null, "sayHello", "", "", new Class[] {}, new Object[] {"1"})));
}
@Test
void argpMatch() {
DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
List<StringMatch> argpMatch = new ArrayList<>();
StringMatch first = new StringMatch();
first.setExact("java.lang.Long");
StringMatch second = new StringMatch();
second.setRegex(".*");
argpMatch.add(first);
argpMatch.add(second);
dubboMethodMatch.setArgp(argpMatch);
assertTrue(dubboMethodMatch.isMatch(
new RpcInvocation(null, "sayHello", "", "", new Class[] {Long.class, String.class}, new Object[] {})));
assertFalse(dubboMethodMatch.isMatch(new RpcInvocation(
null, "sayHello", "", "", new Class[] {Long.class, String.class, String.class}, new Object[] {})));
assertFalse(
dubboMethodMatch.isMatch(new RpcInvocation(null, "sayHello", "", "", new Class[] {}, new Object[] {})));
}
@Test
void parametersMatch() {
DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
List<DubboMethodArg> parametersMatch = new ArrayList<>();
// ----- index 0
{
DubboMethodArg dubboMethodArg0 = new DubboMethodArg();
dubboMethodArg0.setIndex(0);
ListDoubleMatch listDoubleMatch = new ListDoubleMatch();
List<DoubleMatch> oneof = new ArrayList<>();
DoubleMatch doubleMatch1 = new DoubleMatch();
doubleMatch1.setExact(10.0);
oneof.add(doubleMatch1);
listDoubleMatch.setOneof(oneof);
dubboMethodArg0.setNum_value(listDoubleMatch);
parametersMatch.add(dubboMethodArg0);
}
// -----index 1
{
DubboMethodArg dubboMethodArg1 = new DubboMethodArg();
dubboMethodArg1.setIndex(1);
ListStringMatch listStringMatch = new ListStringMatch();
List<StringMatch> oneof = new ArrayList<>();
StringMatch stringMatch1 = new StringMatch();
stringMatch1.setExact("sayHello");
oneof.add(stringMatch1);
listStringMatch.setOneof(oneof);
dubboMethodArg1.setStr_value(listStringMatch);
parametersMatch.add(dubboMethodArg1);
}
dubboMethodMatch.setArgs(parametersMatch);
assertTrue(dubboMethodMatch.isMatch(new RpcInvocation(
null, "test", "", "", new Class[] {int.class, String.class}, new Object[] {10, "sayHello"})));
assertFalse(dubboMethodMatch.isMatch(new RpcInvocation(
null, "test", "", "", new Class[] {int.class, String.class}, 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(new RpcInvocation(
null, "test", "", "", new Class[] {int.class, String.class, boolean.class}, new Object[] {
10, "sayHello", true
})));
assertFalse(dubboMethodMatch.isMatch(new RpcInvocation(
null, "test", "", "", new Class[] {int.class, String.class, boolean.class}, new Object[] {
10, "sayHello", false
})));
}
}

View File

@ -1,49 +0,0 @@
/*
* 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.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class ListBoolMatchTest {
@Test
void isMatch() {
ListBoolMatch listBoolMatch = new ListBoolMatch();
List<BoolMatch> oneof = new ArrayList<>();
BoolMatch boolMatch1 = new BoolMatch();
boolMatch1.setExact(true);
oneof.add(boolMatch1);
listBoolMatch.setOneof(oneof);
assertTrue(listBoolMatch.isMatch(true));
assertFalse(listBoolMatch.isMatch(false));
BoolMatch boolMatch2 = new BoolMatch();
boolMatch2.setExact(false);
oneof.add(boolMatch2);
listBoolMatch.setOneof(oneof);
assertTrue(listBoolMatch.isMatch(false));
}
}

View File

@ -1,49 +0,0 @@
/*
* 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.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class ListDoubleMatchTest {
@Test
void isMatch() {
ListDoubleMatch listDoubleMatch = new ListDoubleMatch();
List<DoubleMatch> oneof = new ArrayList<>();
DoubleMatch doubleMatch1 = new DoubleMatch();
doubleMatch1.setExact(10.0);
DoubleMatch doubleMatch2 = new DoubleMatch();
doubleMatch2.setExact(11.0);
oneof.add(doubleMatch1);
oneof.add(doubleMatch2);
listDoubleMatch.setOneof(oneof);
assertTrue(listDoubleMatch.isMatch(10.0));
assertTrue(listDoubleMatch.isMatch(11.0));
assertFalse(listDoubleMatch.isMatch(12.0));
}
}

View File

@ -1,50 +0,0 @@
/*
* 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.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class ListStringMatchTest {
@Test
void isMatch() {
ListStringMatch listStringMatch = new ListStringMatch();
List<StringMatch> oneof = new ArrayList<>();
StringMatch stringMatch1 = new StringMatch();
stringMatch1.setExact("1");
StringMatch stringMatch2 = new StringMatch();
stringMatch2.setExact("2");
oneof.add(stringMatch1);
oneof.add(stringMatch2);
listStringMatch.setOneof(oneof);
assertTrue(listStringMatch.isMatch("1"));
assertTrue(listStringMatch.isMatch("2"));
assertFalse(listStringMatch.isMatch("3"));
}
}

View File

@ -1,76 +0,0 @@
/*
* 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;
class StringMatchTest {
@Test
void exactMatch() {
StringMatch stringMatch = new StringMatch();
stringMatch.setExact("qinliujie");
assertTrue(stringMatch.isMatch("qinliujie"));
assertFalse(stringMatch.isMatch("other"));
assertFalse(stringMatch.isMatch(null));
}
@Test
void prefixMatch() {
StringMatch stringMatch = new StringMatch();
stringMatch.setPrefix("org.apache.dubbo.rpc.cluster.router.mesh");
assertTrue(stringMatch.isMatch("org.apache.dubbo.rpc.cluster.router.mesh.test"));
assertFalse(stringMatch.isMatch("com.alibaba.hsf"));
assertFalse(stringMatch.isMatch(null));
}
@Test
void regxMatch() {
StringMatch stringMatch = new StringMatch();
stringMatch.setRegex("org.apache.dubbo.rpc.cluster.router.mesh.*");
assertTrue(stringMatch.isMatch("org.apache.dubbo.rpc.cluster.router.mesh"));
assertTrue(stringMatch.isMatch("org.apache.dubbo.rpc.cluster.router.mesh.test"));
assertFalse(stringMatch.isMatch("com.alibaba.hsf"));
assertFalse(stringMatch.isMatch("com.taobao"));
}
@Test
void emptyMatch() {
StringMatch stringMatch = new StringMatch();
stringMatch.setEmpty("empty");
assertFalse(stringMatch.isMatch("com.alibaba.hsf"));
assertTrue(stringMatch.isMatch(""));
assertTrue(stringMatch.isMatch(null));
}
@Test
void noEmptyMatch() {
StringMatch stringMatch = new StringMatch();
stringMatch.setNoempty("noempty");
assertTrue(stringMatch.isMatch("com.alibaba.hsf"));
assertFalse(stringMatch.isMatch(""));
assertFalse(stringMatch.isMatch(null));
}
}

View File

@ -1,202 +0,0 @@
/*
* 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 java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class MeshRuleDispatcherTest {
@Test
void post() {
MeshRuleDispatcher meshRuleDispatcher = new MeshRuleDispatcher("TestApp");
Map<String, List<Map<String, Object>>> ruleMap = new HashMap<>();
List<Map<String, Object>> type1 = new LinkedList<>();
List<Map<String, Object>> type2 = new LinkedList<>();
List<Map<String, Object>> type3 = new LinkedList<>();
ruleMap.put("Type1", type1);
ruleMap.put("Type2", type2);
ruleMap.put("Type3", type3);
AtomicInteger count = new AtomicInteger(0);
MeshRuleListener listener1 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
Assertions.assertEquals("TestApp", appName);
Assertions.assertEquals(System.identityHashCode(type1), System.identityHashCode(rules));
count.incrementAndGet();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type1";
}
};
MeshRuleListener listener2 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
Assertions.assertEquals("TestApp", appName);
Assertions.assertEquals(System.identityHashCode(type2), System.identityHashCode(rules));
count.incrementAndGet();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type2";
}
};
MeshRuleListener listener4 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
Assertions.fail();
}
@Override
public void clearRule(String appName) {
Assertions.assertEquals("TestApp", appName);
count.incrementAndGet();
}
@Override
public String ruleSuffix() {
return "Type4";
}
};
meshRuleDispatcher.register(listener1);
meshRuleDispatcher.register(listener2);
meshRuleDispatcher.register(listener4);
meshRuleDispatcher.post(ruleMap);
Assertions.assertEquals(3, count.get());
}
@Test
void register() {
MeshRuleDispatcher meshRuleDispatcher = new MeshRuleDispatcher("TestApp");
MeshRuleListener listener1 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type1";
}
};
meshRuleDispatcher.register(listener1);
meshRuleDispatcher.register(listener1);
Assertions.assertEquals(
1, meshRuleDispatcher.getListenerMap().get("Type1").size());
Assertions.assertTrue(meshRuleDispatcher.getListenerMap().get("Type1").contains(listener1));
}
@Test
void unregister() {
MeshRuleDispatcher meshRuleDispatcher = new MeshRuleDispatcher("TestApp");
MeshRuleListener listener1 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type1";
}
};
MeshRuleListener listener2 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type1";
}
};
MeshRuleListener listener3 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type2";
}
};
meshRuleDispatcher.register(listener1);
meshRuleDispatcher.register(listener2);
meshRuleDispatcher.register(listener3);
Assertions.assertEquals(
2, meshRuleDispatcher.getListenerMap().get("Type1").size());
Assertions.assertTrue(meshRuleDispatcher.getListenerMap().get("Type1").contains(listener1));
Assertions.assertTrue(meshRuleDispatcher.getListenerMap().get("Type1").contains(listener2));
Assertions.assertEquals(
1, meshRuleDispatcher.getListenerMap().get("Type2").size());
Assertions.assertTrue(meshRuleDispatcher.getListenerMap().get("Type2").contains(listener3));
meshRuleDispatcher.unregister(listener1);
Assertions.assertEquals(
1, meshRuleDispatcher.getListenerMap().get("Type1").size());
Assertions.assertTrue(meshRuleDispatcher.getListenerMap().get("Type1").contains(listener2));
Assertions.assertEquals(
1, meshRuleDispatcher.getListenerMap().get("Type2").size());
Assertions.assertTrue(meshRuleDispatcher.getListenerMap().get("Type2").contains(listener3));
meshRuleDispatcher.unregister(listener2);
Assertions.assertNull(meshRuleDispatcher.getListenerMap().get("Type1"));
Assertions.assertEquals(
1, meshRuleDispatcher.getListenerMap().get("Type2").size());
Assertions.assertTrue(meshRuleDispatcher.getListenerMap().get("Type2").contains(listener3));
meshRuleDispatcher.unregister(listener3);
Assertions.assertNull(meshRuleDispatcher.getListenerMap().get("Type1"));
Assertions.assertNull(meshRuleDispatcher.getListenerMap().get("Type2"));
}
}