Merge 73daf80b85 into ca1ae1f4b6
This commit is contained in:
commit
4c464774ce
|
|
@ -17,8 +17,8 @@
|
|||
package org.apache.dubbo.rpc.cluster.configurator.parser.model;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.AddressMatch;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.ListStringMatch;
|
||||
import org.apache.dubbo.rpc.cluster.configurator.parser.model.match.AddressMatch;
|
||||
import org.apache.dubbo.rpc.cluster.configurator.parser.model.match.ListStringMatch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
package org.apache.dubbo.rpc.cluster.configurator.parser.model;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
|
||||
import org.apache.dubbo.rpc.cluster.configurator.parser.model.match.StringMatch;
|
||||
|
||||
public class ParamMatch {
|
||||
private String key;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* 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;
|
||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model.match;
|
||||
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* 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;
|
||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model.match;
|
||||
|
||||
public class BoolMatch {
|
||||
private Boolean exact;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* 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;
|
||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model.match;
|
||||
|
||||
public class DoubleMatch {
|
||||
private Double exact;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* 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;
|
||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model.match;
|
||||
|
||||
public class DoubleRangeMatch {
|
||||
private Double start;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* 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;
|
||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model.match;
|
||||
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.util.TracingContextProvider;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* 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;
|
||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model.match;
|
||||
|
||||
public class DubboMethodArg {
|
||||
private int index;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* 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;
|
||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model.match;
|
||||
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.support.RpcUtils;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* 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;
|
||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model.match;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* 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;
|
||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model.match;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* 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;
|
||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model.match;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* 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;
|
||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model.match;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {}
|
||||
|
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {}
|
||||
|
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
package org.apache.dubbo.rpc.cluster.router.tag.model;
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
|
||||
import org.apache.dubbo.rpc.cluster.configurator.parser.model.match.StringMatch;
|
||||
|
||||
public class ParamMatch {
|
||||
private String key;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import org.apache.dubbo.rpc.cluster.configurator.absent.AbsentConfigurator;
|
|||
import org.apache.dubbo.rpc.cluster.configurator.consts.UrlConstant;
|
||||
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ConditionMatch;
|
||||
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ParamMatch;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
|
||||
import org.apache.dubbo.rpc.cluster.configurator.parser.model.match.StringMatch;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue