Skip to content

Commit

Permalink
feat: config prefix match by trie && fix: InstanceByProto get ns from…
Browse files Browse the repository at this point in the history
… instance (#567)
  • Loading branch information
shedfreewu authored Nov 20, 2024
1 parent 1ccd1bb commit 0907ebc
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ public TrieNode<T> getSubNode(String nodeKey) {
return null;
}

public boolean isEmptyChildren() {
return children.isEmpty();
}

// only for build trie
public TrieNode<T> getOrCreateSubNode(String path) {
if (path.startsWith("{") && path.endsWith("}")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public static boolean matchStringValue(MatchStringType matchType, String actualV
switch (matchType) {
case EXACT: {
if (useTrieNode && trieNodeFunction != null) {
return ApiTrieUtil.checkSimple(trieNodeFunction.apply(matchValue), actualValue);
return TrieUtil.checkSimpleApi(trieNodeFunction.apply(matchValue), actualValue);
}
return StringUtils.equalsIgnoreCase(actualValue, matchValue);
}
Expand All @@ -104,15 +104,15 @@ public static boolean matchStringValue(MatchStringType matchType, String actualV
}
case NOT_EQUALS: {
if (useTrieNode && trieNodeFunction != null) {
return !ApiTrieUtil.checkSimple(trieNodeFunction.apply(matchValue), actualValue);
return !TrieUtil.checkSimpleApi(trieNodeFunction.apply(matchValue), actualValue);
}
return !StringUtils.equalsIgnoreCase(actualValue, matchValue);
}
case IN: {
String[] tokens = matchValue.split(",");
for (String token : tokens) {
if (useTrieNode && trieNodeFunction != null) {
if (ApiTrieUtil.checkSimple(trieNodeFunction.apply(matchValue), actualValue)) {
if (TrieUtil.checkSimpleApi(trieNodeFunction.apply(matchValue), actualValue)) {
return true;
}
} else {
Expand All @@ -127,7 +127,7 @@ public static boolean matchStringValue(MatchStringType matchType, String actualV
String[] tokens = matchValue.split(",");
for (String token : tokens) {
if (useTrieNode && trieNodeFunction != null) {
if (ApiTrieUtil.checkSimple(trieNodeFunction.apply(matchValue), actualValue)) {
if (TrieUtil.checkSimpleApi(trieNodeFunction.apply(matchValue), actualValue)) {
return false;
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,20 @@
import com.tencent.polaris.api.pojo.HttpElement;
import com.tencent.polaris.api.pojo.TrieNode;

public class ApiTrieUtil {
public class TrieUtil {

/**
* @param apiPath
* @return TrieNode
*/
public static TrieNode<String> buildSimpleTrieNode(String apiPath) {
public static TrieNode<String> buildSimpleApiTrieNode(String apiPath) {
if (StringUtils.isEmpty(apiPath)) {
return null;
}
return buildSimpleTrieNode(new String[]{apiPath});
return buildSimpleApiTrieNode(new String[]{apiPath});
}

public static TrieNode<String> buildSimpleTrieNode(String[] apiPathInfoList) {
public static TrieNode<String> buildSimpleApiTrieNode(String[] apiPathInfoList) {
if (apiPathInfoList.length == 0) {
return null;
}
Expand Down Expand Up @@ -72,7 +72,7 @@ public static TrieNode<String> buildSimpleTrieNode(String[] apiPathInfoList) {
return root;
}

public static boolean checkSimple(TrieNode<String> root, String apiPathInfo) {
public static boolean checkSimpleApi(TrieNode<String> root, String apiPathInfo) {
if (root == null) {
return false;
}
Expand Down Expand Up @@ -108,4 +108,53 @@ public static boolean checkSimple(TrieNode<String> root, String apiPathInfo) {
return false;
}

public static TrieNode<String> buildConfigTrieNode(String prefix) {
TrieNode<String> root = new TrieNode<>(TrieNode.ROOT_PATH);
return buildConfigTrieNode(prefix, root);
}

public static TrieNode<String> buildConfigTrieNode(String prefix, TrieNode<String> root) {
if (StringUtils.isEmpty(prefix)) {
return null;
}
// split by .
String[] prefixes = prefix.split("\\.");
TrieNode<String> node = root;
for (String s : prefixes) {
node = node.getOrCreateSubNode(s);
}
return root;
}

public static boolean checkConfig(TrieNode<String> root, String config) {
if (root == null || root.isEmptyChildren() || StringUtils.isEmpty(config)) {
return false;
}

String[] entities = config.split("\\.");

TrieNode<String> node = root;
for (String entity : entities) {
// empty children means leaf in config matching
if (node.isEmptyChildren()) {
return true;
}
// for list
if (entity.indexOf("[") < entity.indexOf("]")) {
entity = entity.substring(0, entity.indexOf("["));
}
node = node.getSubNode(entity);
if (node == null) {
return false;
}
}

if (node != null && node.isEmptyChildren()) {
// exact match
return true;
} else {
// not match or config is shorter than prefix
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package com.tencent.polaris.client.pojo;

import com.google.protobuf.StringValue;
import com.google.protobuf.UInt32Value;
import com.tencent.polaris.api.pojo.CircuitBreakerStatus;
import com.tencent.polaris.api.pojo.DetectResult;
Expand All @@ -30,6 +31,7 @@
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
* 通过PB对象封装的实例信息
Expand Down Expand Up @@ -78,7 +80,8 @@ public int hashCode() {

@Override
public String getNamespace() {
return serviceKey.getNamespace();
return Optional.of(instance).map(ServiceProto.Instance::getNamespace).
map(StringValue::getValue).orElse(serviceKey.getNamespace());
}

@Override
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Tencent is pleased to support the open source community by making Polaris available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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 com.tencent.polaris.api.utils;

import com.tencent.polaris.api.pojo.TrieNode;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Test for {@link TrieUtil}.
*/
public class TrieUtilTest {

@Test
public void testCheckSimple() {
TrieNode<String> rootWithMethod = TrieUtil.buildSimpleApiTrieNode("/echo/{param}-GET");
TrieNode<String> rootWithoutMethod = TrieUtil.buildSimpleApiTrieNode("/echo/{param}-GET");
assertThat(TrieUtil.checkSimpleApi(rootWithMethod, "/echo/test")).isTrue();
assertThat(TrieUtil.checkSimpleApi(rootWithoutMethod, "/echo/test")).isTrue();
assertThat(TrieUtil.checkSimpleApi(rootWithoutMethod, "/echoo/test")).isFalse();
assertThat(TrieUtil.checkSimpleApi(rootWithoutMethod, "/echo/")).isFalse();
assertThat(TrieUtil.checkSimpleApi(rootWithMethod, "/echo/test-GET")).isTrue();
assertThat(TrieUtil.checkSimpleApi(rootWithoutMethod, "/echo/test-GET")).isTrue();
assertThat(TrieUtil.checkSimpleApi(rootWithoutMethod, "/echo/test-POST")).isTrue();
assertThat(TrieUtil.checkSimpleApi(rootWithoutMethod, "/echo/test-POST")).isTrue();
assertThat(TrieUtil.checkSimpleApi(rootWithoutMethod, "/echoo/test-GET")).isFalse();
assertThat(TrieUtil.checkSimpleApi(rootWithoutMethod, "/echo/-GET")).isFalse();
}

@Test
public void testCheckConfig() {
TrieNode<String> root1 = TrieUtil.buildConfigTrieNode("provider.config");
assertThat(TrieUtil.checkConfig(root1, "provider.config.test")).isTrue();
assertThat(TrieUtil.checkConfig(root1, "provider.config.test.aaa")).isTrue();
assertThat(TrieUtil.checkConfig(root1, "provider.config2.test")).isFalse();
assertThat(TrieUtil.checkConfig(root1, "provider")).isFalse();
assertThat(TrieUtil.checkConfig(root1, "provider.config")).isTrue();
assertThat(TrieUtil.checkConfig(root1, "provider.config.nameList[1]")).isTrue();
assertThat(TrieUtil.checkConfig(root1, null)).isFalse();

TrieNode<String> root2 = TrieUtil.buildConfigTrieNode("provider.conf");
assertThat(TrieUtil.checkConfig(root2, "provider.conf.test")).isTrue();
assertThat(TrieUtil.checkConfig(root2, "provider.conf.test.aaa")).isTrue();
assertThat(TrieUtil.checkConfig(root2, "provider.config2.test")).isFalse();
assertThat(TrieUtil.checkConfig(root2, "provider")).isFalse();
assertThat(TrieUtil.checkConfig(root2, "provider.config")).isFalse();
assertThat(TrieUtil.checkConfig(root2, "provider.conf")).isTrue();
assertThat(TrieUtil.checkConfig(root2, "provider.conf.nameList[1]")).isTrue();

TrieNode<String> root3 = new TrieNode<>(TrieNode.ROOT_PATH);
assertThat(TrieUtil.checkConfig(root3, "provider.config.test")).isFalse();
}

@Test
public void testCheckConfig2() {
TrieNode<String> root1 = TrieUtil.buildConfigTrieNode("provider.config.list");
assertThat(TrieUtil.checkConfig(root1, "provider.config.list[1]")).isTrue();
assertThat(TrieUtil.checkConfig(root1, "provider.config.list[1].name")).isTrue();
assertThat(TrieUtil.checkConfig(root1, "provider.config.name")).isFalse();

TrieNode<String> root2 = TrieUtil.buildConfigTrieNode("provider.config.map");
assertThat(TrieUtil.checkConfig(root2, "provider.config.map.key1")).isTrue();
assertThat(TrieUtil.checkConfig(root2, "provider.config.map.key2")).isTrue();
assertThat(TrieUtil.checkConfig(root1, "provider.config.name")).isFalse();

TrieNode<String> root3 = new TrieNode<>(TrieNode.ROOT_PATH);
assertThat(TrieUtil.checkConfig(root3, "provider.config.test")).isFalse();
}

@Test
public void testCheckConfigMergeRoot() {
TrieNode<String> root = new TrieNode<>(TrieNode.ROOT_PATH);

TrieUtil.buildConfigTrieNode("provider.config", root);
TrieUtil.buildConfigTrieNode("provider.conf", root);

assertThat(TrieUtil.checkConfig(root, "provider.config.test")).isTrue();
assertThat(TrieUtil.checkConfig(root, "provider.config.test.aaa")).isTrue();
assertThat(TrieUtil.checkConfig(root, "provider.config2.test")).isFalse();
assertThat(TrieUtil.checkConfig(root, "provider")).isFalse();
assertThat(TrieUtil.checkConfig(root, "provider.config")).isTrue();
assertThat(TrieUtil.checkConfig(root, "provider.config.nameList[1]")).isTrue();


assertThat(TrieUtil.checkConfig(root, "provider.conf.test")).isTrue();
assertThat(TrieUtil.checkConfig(root, "provider.conf.test.aaa")).isTrue();
assertThat(TrieUtil.checkConfig(root, "provider.config2.test")).isFalse();
assertThat(TrieUtil.checkConfig(root, "provider")).isFalse();
assertThat(TrieUtil.checkConfig(root, "provider.config")).isTrue();
assertThat(TrieUtil.checkConfig(root, "provider.conf")).isTrue();
assertThat(TrieUtil.checkConfig(root, "provider.conf.nameList[1]")).isTrue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@
import com.tencent.polaris.configuration.api.core.ConfigFileGroup;
import com.tencent.polaris.configuration.api.core.ConfigFileGroupMetadata;
import com.tencent.polaris.configuration.api.core.ConfigFileMetadata;
import com.tencent.polaris.logging.LoggerFactory;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ConfigFileGroupManager {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigFileGroupManager.class);
private final Map<ConfigFileGroupMetadata, RevisableConfigFileGroup> configFileGroupCache =
new ConcurrentHashMap<>();
private RetryableConfigFileGroupConnector rpcConnector;
Expand Down Expand Up @@ -69,7 +72,8 @@ public RetryableConfigFileGroupConnector.RetryableValidator getCacheMissedRetryS

public ConfigFileGroup getConfigFileGroup(ConfigFileGroupMetadata metadata) {
if (!enabled) {
throw new RuntimeException("Config file group manager is disabled.");
LOGGER.warn("config file group is not enabled, metadata: {}", metadata);
return null;
}
RevisableConfigFileGroup configFileGroup = configFileGroupCache.get(metadata);
if (configFileGroup == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

package com.tencent.polaris.api.plugin.cache;

import com.tencent.polaris.api.utils.ApiTrieUtil;
import com.tencent.polaris.api.utils.TrieUtil;
import com.tencent.polaris.specification.api.v1.model.ModelProto;

import static com.tencent.polaris.api.plugin.cache.CacheConstants.API_ID;
Expand All @@ -31,12 +31,12 @@ public static void saveApiTrie(ModelProto.MatchString matchString, FlowCache flo
if (matchString != null && matchString.getType() != ModelProto.MatchString.MatchStringType.REGEX) {
if (matchString.getType() == ModelProto.MatchString.MatchStringType.EXACT || matchString.getType() == ModelProto.MatchString.MatchStringType.NOT_EQUALS) {
flowCache.loadPluginCacheObject(API_ID, matchString.getValue().getValue(),
path -> ApiTrieUtil.buildSimpleTrieNode((String) path));
path -> TrieUtil.buildSimpleApiTrieNode((String) path));
} else if (matchString.getType() == ModelProto.MatchString.MatchStringType.IN || matchString.getType() == ModelProto.MatchString.MatchStringType.NOT_IN) {
String[] apis = matchString.getValue().getValue().split(",");
for (String api : apis) {
flowCache.loadPluginCacheObject(API_ID, api,
path -> ApiTrieUtil.buildSimpleTrieNode((String) path));
path -> TrieUtil.buildSimpleApiTrieNode((String) path));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import com.tencent.polaris.api.plugin.compose.Extensions;
import com.tencent.polaris.api.pojo.*;
import com.tencent.polaris.api.rpc.RequestBaseEntity;
import com.tencent.polaris.api.utils.ApiTrieUtil;
import com.tencent.polaris.api.utils.TrieUtil;
import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.api.utils.RuleUtils;
import com.tencent.polaris.api.utils.StringUtils;
Expand Down Expand Up @@ -221,7 +221,7 @@ public void postContextInit(Extensions ctx) throws PolarisException {
return null;
}
FlowCache flowCache = extensions.getFlowCache();
return flowCache.loadPluginCacheObject(API_ID, key, path -> ApiTrieUtil.buildSimpleTrieNode((String) path));
return flowCache.loadPluginCacheObject(API_ID, key, path -> TrieUtil.buildSimpleApiTrieNode((String) path));
};
}

Expand Down
Loading

0 comments on commit 0907ebc

Please sign in to comment.