diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/utils/ReflectUtils.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/utils/ReflectUtils.java index 53103de1f4..64313450bd 100644 --- a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/utils/ReflectUtils.java +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/utils/ReflectUtils.java @@ -54,11 +54,15 @@ public class ReflectUtils { */ private static final Map METHOD_CACHE = new ConcurrentHashMap<>(); + private static final Map>> CLASS_CACHE = new ConcurrentHashMap<>(); + /** * 针对单个类缓存的Field的初始化容量 */ private static final int INIT_CLASS_FILED_CACHE_SIZE = 4; + private static final int EXTRA_LENGTH_FOR_METHOD_KEY = 3; + private ReflectUtils() { } @@ -139,7 +143,6 @@ public static Optional invokeMethod(Class clazz, String methodName, C * @return 结果 */ public static Optional invokeMethod(Object target, Method method, Object[] params) { - setAccessible(method); try { if (params == null) { return Optional.ofNullable(method.invoke(target)); @@ -157,13 +160,15 @@ private static Optional> loadClass(String className) { if (className == null) { return Optional.empty(); } - final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); - try { - return Optional.ofNullable(contextClassLoader.loadClass(className)); - } catch (ClassNotFoundException ignored) { - // 找不到类直接返回 - return Optional.empty(); - } + return CLASS_CACHE.computeIfAbsent(className, value -> { + final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + try { + return Optional.ofNullable(contextClassLoader.loadClass(className)); + } catch (ClassNotFoundException ignored) { + // 找不到类直接返回 + return Optional.empty(); + } + }); } /** @@ -184,7 +189,7 @@ public static Optional findMethod(Class clazz, String methodName, Cla if (method != null) { return Optional.of(method); } - method = clazz.getDeclaredMethod(methodName, paramsType); + method = setAccessible(clazz.getDeclaredMethod(methodName, paramsType)); METHOD_CACHE.put(methodKey, method); return Optional.of(method); } catch (NoSuchMethodException ex) { @@ -273,8 +278,8 @@ public static Optional> findConstructor(Class clazz, Class[ private static String buildMethodKey(Class clazz, String methodName, Class[] paramsType) { final String name = clazz.getName(); - final StringBuilder sb = new StringBuilder(name); - sb.append("#").append(methodName).append("("); + final StringBuilder sb = new StringBuilder(name.length() + methodName.length() + EXTRA_LENGTH_FOR_METHOD_KEY); + sb.append(name).append("#").append(methodName).append("("); if (paramsType != null) { for (Class paramType : paramsType) { sb.append(paramType.getName()).append(","); @@ -299,15 +304,12 @@ public static void setFieldValue(Object target, String fieldName, Object value) if (isFinalField(field)) { updateFinalModifierField(field); } - AccessController.doPrivileged((PrivilegedAction) () -> { - try { - field.set(target, value); - } catch (IllegalAccessException ex) { - LOGGER.warning(String.format(Locale.ENGLISH, "Set value for field [%s] failed! %s", fieldName, - ex.getMessage())); - } - return value; - }); + try { + field.set(target, value); + } catch (IllegalAccessException ex) { + LOGGER.warning(String.format(Locale.ENGLISH, "Set value for field [%s] failed! %s", fieldName, + ex.getMessage())); + } } /** @@ -318,8 +320,6 @@ public static void setFieldValue(Object target, String fieldName, Object value) public static void updateFinalModifierField(Field field) { final Field modifiersField = getField(Field.class, "modifiers"); if (modifiersField != null) { - setAccessible(field); - setAccessible(modifiersField); try { modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); } catch (IllegalAccessException ex) { @@ -415,8 +415,8 @@ private static Field getField(Class clazz, String fieldName) { Field field = cache.get(fieldName); try { if (field == null) { - field = clazz.getDeclaredField(fieldName); - cache.putIfAbsent(fieldName, setAccessible(field)); + field = setAccessible(clazz.getDeclaredField(fieldName)); + cache.putIfAbsent(fieldName, field); } } catch (IllegalArgumentException | NoSuchFieldException ex) { if (clazz.getSuperclass() != null) { diff --git a/sermant-plugins/sermant-flowcontrol/flowcontrol-service/src/main/java/com/huawei/flowcontrol/res4j/chain/AbstractChainHandler.java b/sermant-plugins/sermant-flowcontrol/flowcontrol-service/src/main/java/com/huawei/flowcontrol/res4j/chain/AbstractChainHandler.java index e3f0672dae..e9c3d7c5ed 100644 --- a/sermant-plugins/sermant-flowcontrol/flowcontrol-service/src/main/java/com/huawei/flowcontrol/res4j/chain/AbstractChainHandler.java +++ b/sermant-plugins/sermant-flowcontrol/flowcontrol-service/src/main/java/com/huawei/flowcontrol/res4j/chain/AbstractChainHandler.java @@ -20,7 +20,6 @@ import com.huawei.flowcontrol.common.entity.RequestEntity.RequestType; import com.huawei.flowcontrol.res4j.chain.context.RequestContext; -import java.util.Locale; import java.util.Set; /** @@ -31,6 +30,8 @@ * @since 2022-07-11 */ public abstract class AbstractChainHandler implements RequestHandler, Comparable { + private static final int EXTRA_LENGTH_FOR_METHOD_CACHE_KEY = 11; + private AbstractChainHandler next; @Override @@ -83,7 +84,14 @@ private boolean isNeedSkip(AbstractChainHandler tmp, RequestContext context, Set } private String skipCacheKey(AbstractChainHandler tmp) { - return String.format(Locale.ENGLISH, "%s_%s_skip_flag", tmp.direct(), tmp.getClass().getName()); + String className = tmp.getClass().getName(); + RequestType direct = tmp.direct(); + + // 初始化StringBuilder的长度是为了性能 + StringBuilder sb = + new StringBuilder(className.length() + direct.name().length() + EXTRA_LENGTH_FOR_METHOD_CACHE_KEY); + sb.append(direct).append("_").append(className).append("_skip_flag"); + return sb.toString(); } /** diff --git a/sermant-plugins/sermant-flowcontrol/flowcontrol-service/src/main/java/com/huawei/flowcontrol/res4j/chain/HandlerChainEntry.java b/sermant-plugins/sermant-flowcontrol/flowcontrol-service/src/main/java/com/huawei/flowcontrol/res4j/chain/HandlerChainEntry.java index 0c2fd8ae0d..c6f1174e06 100644 --- a/sermant-plugins/sermant-flowcontrol/flowcontrol-service/src/main/java/com/huawei/flowcontrol/res4j/chain/HandlerChainEntry.java +++ b/sermant-plugins/sermant-flowcontrol/flowcontrol-service/src/main/java/com/huawei/flowcontrol/res4j/chain/HandlerChainEntry.java @@ -25,7 +25,6 @@ import com.huaweicloud.sermant.core.common.LoggerFactory; -import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; @@ -84,9 +83,13 @@ public void onDubboBefore(String sourceName, RequestEntity requestEntity, FlowCo } private String formatSourceName(String sourceName, boolean isProvider) { - return String.format(Locale.ENGLISH, "%s%s", - isProvider ? HandlerConstants.THREAD_LOCAL_DUBBO_PROVIDER_PREFIX - : HandlerConstants.THREAD_LOCAL_DUBBO_CONSUMER_PREFIX, sourceName); + String prefix = isProvider ? HandlerConstants.THREAD_LOCAL_DUBBO_PROVIDER_PREFIX + : HandlerConstants.THREAD_LOCAL_DUBBO_CONSUMER_PREFIX; + + // 初始化StringBuilder的长度是为了性能 + StringBuilder sb = new StringBuilder(prefix.length() + sourceName.length()); + sb.append(prefix).append(sourceName); + return sb.toString(); } /** diff --git a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/interceptor/ContextFilterInterceptor.java b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/interceptor/ContextFilterInterceptor.java index c6a34b0cc6..a27aa2f1f7 100644 --- a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/interceptor/ContextFilterInterceptor.java +++ b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/interceptor/ContextFilterInterceptor.java @@ -20,6 +20,7 @@ import com.huaweicloud.sermant.core.plugin.agent.interceptor.AbstractInterceptor; import com.huaweicloud.sermant.core.service.ServiceManager; import com.huaweicloud.sermant.router.common.request.RequestHeader; +import com.huaweicloud.sermant.router.common.utils.CollectionUtils; import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; import com.huaweicloud.sermant.router.dubbo.service.DubboConfigService; import com.huaweicloud.sermant.router.dubbo.utils.DubboReflectUtils; @@ -49,9 +50,12 @@ public ContextFilterInterceptor() { @Override public ExecuteContext before(ExecuteContext context) { + Set matchKeys = configService.getMatchKeys(); + if (CollectionUtils.isEmpty(matchKeys)) { + return context; + } Map attachments = DubboReflectUtils.getAttachments(context.getArguments()[1]); Map> header = new HashMap<>(); - Set matchKeys = configService.getMatchKeys(); matchKeys.forEach(key -> { if (attachments.containsKey(key)) { String value = Optional.ofNullable(attachments.get(key)).map(String::valueOf).orElse(null); diff --git a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/utils/DubboReflectUtils.java b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/utils/DubboReflectUtils.java index 6950f07e88..4b1981127b 100644 --- a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/utils/DubboReflectUtils.java +++ b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/utils/DubboReflectUtils.java @@ -156,7 +156,7 @@ public static Map getAttachments(Object obj) { if (obj == null) { return Collections.emptyMap(); } - String className = obj.getClass().getCanonicalName().startsWith("com.alibaba.dubbo") + String className = obj.getClass().getName().startsWith("com.alibaba.dubbo") ? ALIBABA_RPC_CONTEXT_CLASS_NAME : APACHE_RPC_CONTEXT_CLASS_NAME; Map attachments = new HashMap<>(getAttachmentsFromContext(className)); attachments.putAll(getAttachmentsByInvocation(obj)); diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceImpl.java b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceImpl.java index dd331d6be0..7c7a160b8b 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceImpl.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceImpl.java @@ -57,6 +57,10 @@ public class AbstractDirectoryServiceImpl implements AbstractDirectoryService { // dubbo请求参数中是否为consumer的value值 private static final String CONSUMER_VALUE = "consumer"; + private static final String DASH = "-"; + + private static final String POINT = "."; + private final RouterConfig routerConfig; // 用于过滤实例的tags集合,value为null,代表含有该标签的实例全部过滤,不判断value值 @@ -69,7 +73,8 @@ public AbstractDirectoryServiceImpl() { routerConfig = PluginConfigManager.getPluginConfig(RouterConfig.class); allMismatchTags = new HashMap<>(); for (String requestTag : routerConfig.getRequestTags()) { - allMismatchTags.put(requestTag, null); + // dubbo会把key中的"-"替换成"." + allMismatchTags.put(requestTag.replace(DASH, POINT), null); } // 所有实例都含有version,所以不能存入null值 @@ -186,7 +191,7 @@ private List getTargetInvokersByRules(List invokers, Object invo if (RouterConfiguration.isInValid(configuration)) { return invokers; } - String interfaceName = getGroup(queryMap) + "/" + serviceInterface + "." + String interfaceName = getGroup(queryMap) + "/" + serviceInterface + POINT + DubboReflectUtils.getMethodName(invocation) + ":" + getVersion(queryMap); List rules = RuleUtils .getRules(configuration, targetService, interfaceName, DubboCache.INSTANCE.getAppName()); @@ -196,7 +201,7 @@ private List getTargetInvokersByRules(List invokers, Object invo return RuleStrategyHandler.INSTANCE.getMatchInvokers(targetService, invokers, routes); } return RuleStrategyHandler.INSTANCE - .getMismatchInvokers(targetService, invokers, RuleUtils.getTags(rules), true); + .getMismatchInvokers(targetService, invokers, RuleUtils.getTags(rules, true), true); } private List getTargetInvokersByRequest(String targetName, List invokers, Object invocation) { @@ -215,10 +220,15 @@ private List getTargetInvokersByRequest(String targetName, List if (!requestTags.contains(key)) { continue; } - mismatchTags.put(key, null); + String replaceDashKey = key; + if (replaceDashKey.contains(DASH)) { + // dubbo会把key中的"-"替换成"." + replaceDashKey = replaceDashKey.replace(DASH, POINT); + } + mismatchTags.put(replaceDashKey, null); String value = Optional.ofNullable(attachments.get(key)).map(String::valueOf).orElse(null); if (StringUtils.isExist(value)) { - tags.put(key, value); + tags.put(replaceDashKey, value); } } if (StringUtils.isExist(tags.get(RouterConstant.DUBBO_VERSION_KEY))) { diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandler.java b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandler.java index fa569cab6d..c03bbc00a1 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandler.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandler.java @@ -50,7 +50,7 @@ public enum RuleStrategyHandler { * @return 标签应用的invokers */ public List getMatchInvokers(String serviceName, List invokers, List routes) { - return ruleStrategy.getMatchInstances(serviceName, invokers, routes); + return ruleStrategy.getMatchInstances(serviceName, invokers, routes, true); } /** diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/instance/MatchInstanceStrategy.java b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/instance/MatchInstanceStrategy.java index 7277d0062b..7f90c785a6 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/instance/MatchInstanceStrategy.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/instance/MatchInstanceStrategy.java @@ -56,8 +56,6 @@ private String getKey(String tag) { if (VERSION_KEY.equals(tag)) { return RouterConstant.VERSION_KEY; } - - // dubbo会把key中的"-"替换成"." - return RouterConstant.PARAMETERS_KEY_PREFIX + tag.replace("-", "."); + return RouterConstant.PARAMETERS_KEY_PREFIX + tag; } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/instance/MismatchInstanceStrategy.java b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/instance/MismatchInstanceStrategy.java index b7713d849f..ec94b45344 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/instance/MismatchInstanceStrategy.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/instance/MismatchInstanceStrategy.java @@ -66,8 +66,6 @@ private String getKey(String tag) { if (VERSION_KEY.equals(tag)) { return RouterConstant.VERSION_KEY; } - - // dubbo会把key中的"-"替换成"." - return RouterConstant.PARAMETERS_KEY_PREFIX + tag.replace("-", "."); + return RouterConstant.PARAMETERS_KEY_PREFIX + tag; } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/utils/ReflectUtils.java b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/utils/ReflectUtils.java index 9839bf57ad..82d2607d96 100644 --- a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/utils/ReflectUtils.java +++ b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/utils/ReflectUtils.java @@ -44,6 +44,8 @@ public class ReflectUtils { private static final Map> METHOD_MAP = new ConcurrentHashMap<>(); + private static final int EXTRA_LENGTH_FOR_METHOD_KEY = 3; + private ReflectUtils() { } @@ -55,17 +57,7 @@ private ReflectUtils() { * @return 私有字段值 */ public static Optional getFieldValue(Object obj, String fieldName) { - Optional field = FIELD_MAP.computeIfAbsent(obj.getClass().getCanonicalName() + "." + fieldName, key -> { - Class currClass = obj.getClass(); - while (currClass != Object.class) { - try { - return Optional.ofNullable(getAccessibleObject(currClass.getDeclaredField(fieldName))); - } catch (NoSuchFieldException e) { - currClass = currClass.getSuperclass(); - } - } - return Optional.empty(); - }); + Optional field = getField(obj, fieldName); if (field.isPresent()) { try { return Optional.ofNullable(field.get().get(obj)); @@ -153,12 +145,39 @@ private static Optional invoke(Class invokeClass, Object obj, String return Optional.empty(); } + private static Optional getField(Object obj, String fieldName) { + return FIELD_MAP.computeIfAbsent(buildFieldKey(obj, fieldName), key -> { + Class currClass = obj.getClass(); + while (currClass != Object.class) { + try { + return Optional.ofNullable(getAccessibleObject(currClass.getDeclaredField(fieldName))); + } catch (NoSuchFieldException e) { + currClass = currClass.getSuperclass(); + } + } + return Optional.empty(); + }); + } + private static String buildMethodKey(Class clazz, String methodName, Class parameterClass) { - StringBuilder sb = new StringBuilder(clazz.getName()); - sb.append("#").append(methodName).append("("); + String parameterClassName = ""; if (parameterClass != null) { - sb.append(parameterClass.getName()); + parameterClassName = parameterClass.getName(); } - return sb.append(")").toString(); + String className = clazz.getName(); + + // 初始化StringBuilder的长度是为了性能 + StringBuilder sb = new StringBuilder( + className.length() + methodName.length() + parameterClassName.length() + EXTRA_LENGTH_FOR_METHOD_KEY); + sb.append(className).append("#").append(methodName).append("(").append(parameterClassName).append(")"); + return sb.toString(); + } + + private static String buildFieldKey(Object obj, String fieldName) { + // 初始化StringBuilder的长度是为了性能 + String className = obj.getClass().getName(); + StringBuilder sb = new StringBuilder(className.length() + fieldName.length() + 1); + sb.append(className).append(".").append(fieldName); + return sb.toString(); } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/AbstractRuleStrategy.java b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/AbstractRuleStrategy.java index 9417c04f61..d38d0803d1 100644 --- a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/AbstractRuleStrategy.java +++ b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/AbstractRuleStrategy.java @@ -74,8 +74,8 @@ public AbstractRuleStrategy(String source, InstanceStrategy getMatchInstances(String serviceName, List instances, List routes) { - RouteResult result = RuleUtils.getTargetTags(routes); + public List getMatchInstances(String serviceName, List instances, List routes, boolean isReplaceDash) { + RouteResult result = RuleUtils.getTargetTags(routes, isReplaceDash); return getInstances(getStrategy(result.isMatch()), result.getTags(), serviceName, instances, true); } diff --git a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/RuleStrategy.java b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/RuleStrategy.java index 6c1c6169db..796df0f854 100644 --- a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/RuleStrategy.java +++ b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/RuleStrategy.java @@ -35,9 +35,10 @@ public interface RuleStrategy { * @param serviceName 服务名 * @param instances 实例列表 * @param routes 路由规则 + * @param isReplaceDash 是否需要替换破折号为点号(dubbo需要) * @return 路由过滤后的实例 */ - List getMatchInstances(String serviceName, List instances, List routes); + List getMatchInstances(String serviceName, List instances, List routes, boolean isReplaceDash); /** * 根据请求信息选取路由的实例 diff --git a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/utils/RuleUtils.java b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/utils/RuleUtils.java index 4e06efc681..fe145c4781 100644 --- a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/utils/RuleUtils.java +++ b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/utils/RuleUtils.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -89,16 +90,17 @@ public static List getRules(RouterConfiguration configuration, String targ * 获取所有标签 * * @param rules 路由规则 + * @param isReplaceDash 是否需要替换破折号为点号(dubbo需要) * @return 标签 */ - public static List> getTags(List rules) { + public static List> getTags(List rules, boolean isReplaceDash) { if (CollectionUtils.isEmpty(rules)) { return Collections.emptyList(); } List> tags = new ArrayList<>(); for (Rule rule : rules) { for (Route route : rule.getRoute()) { - tags.add(route.getTags()); + tags.add(replaceDash(route.getTags(), isReplaceDash)); } } return tags; @@ -153,9 +155,10 @@ public static Set getMatchKeys() { * 选取路由 * * @param routes 路由规则 + * @param isReplaceDash 是否需要替换破折号为点号(dubbo需要) * @return 目标路由 */ - public static RouteResult getTargetTags(List routes) { + public static RouteResult getTargetTags(List routes, boolean isReplaceDash) { List> tags = new ArrayList<>(); int begin = 1; int num = ThreadLocalRandom.current().nextInt(ONO_HUNDRED) + 1; @@ -164,7 +167,7 @@ public static RouteResult getTargetTags(List routes) { if (weight == null) { continue; } - Map currentTag = route.getTags(); + Map currentTag = replaceDash(route.getTags(), isReplaceDash); if (num >= begin && num <= begin + weight - 1) { return new RouteResult<>(true, currentTag); } @@ -303,6 +306,22 @@ private static void addKeys(Set keys, Map> match } } + private static Map replaceDash(Map tags, boolean isReplaceDash) { + if (!isReplaceDash) { + return tags; + } + Map map = new HashMap<>(); + tags.forEach((key, value) -> { + if (key != null && key.contains("-")) { + // dubbo会把key中的"-"替换成"." + map.put(key.replace("-", "."), value); + } else { + map.put(key, value); + } + }); + return map; + } + /** * 匹配结果 * diff --git a/sermant-plugins/sermant-router/router-config-common/src/test/java/com/huaweicloud/sermant/router/config/utils/RuleUtilsTest.java b/sermant-plugins/sermant-router/router-config-common/src/test/java/com/huaweicloud/sermant/router/config/utils/RuleUtilsTest.java index 5efa3049bf..f948c1d8b0 100644 --- a/sermant-plugins/sermant-router/router-config-common/src/test/java/com/huaweicloud/sermant/router/config/utils/RuleUtilsTest.java +++ b/sermant-plugins/sermant-router/router-config-common/src/test/java/com/huaweicloud/sermant/router/config/utils/RuleUtilsTest.java @@ -56,7 +56,7 @@ public void before() { */ @Test public void testGetTags() { - List> tags = RuleUtils.getTags(list); + List> tags = RuleUtils.getTags(list, false); Assert.assertEquals(2, tags.size()); Assert.assertEquals("1.0.1", tags.get(0).get("version")); Assert.assertEquals("1.0.0", tags.get(1).get("version")); diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/BaseLoadBalancerInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/BaseLoadBalancerInterceptor.java index bf05f9e884..d979765e39 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/BaseLoadBalancerInterceptor.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/BaseLoadBalancerInterceptor.java @@ -51,12 +51,15 @@ public class BaseLoadBalancerInterceptor extends AbstractInterceptor { private final RouterConfig routerConfig; + private final boolean canLoadZuul; + /** * 构造方法 */ public BaseLoadBalancerInterceptor() { loadBalancerService = ServiceManager.getService(LoadBalancerService.class); routerConfig = PluginConfigManager.getPluginConfig(RouterConfig.class); + canLoadZuul = canLoadZuul(); } @Override @@ -98,7 +101,7 @@ private Optional getRequestData() { if (requestData != null) { return Optional.of(requestData); } - if (!canLoadZuul()) { + if (!canLoadZuul) { return Optional.empty(); } RequestContext context = RequestContext.getCurrentContext(); diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptor.java index 1cf01d3d1b..374020047d 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptor.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptor.java @@ -16,7 +16,6 @@ package com.huaweicloud.sermant.router.spring.interceptor; -import com.huaweicloud.sermant.core.common.LoggerFactory; import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; import com.huaweicloud.sermant.core.plugin.agent.interceptor.AbstractInterceptor; import com.huaweicloud.sermant.core.utils.StringUtils; @@ -32,8 +31,6 @@ import feign.Request; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -42,8 +39,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Optional; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Client增强类,发起feign请求方法 @@ -52,10 +47,6 @@ * @since 2022-07-12 */ public class FeignClientInterceptor extends AbstractInterceptor { - private static final Logger LOGGER = LoggerFactory.getLogger(); - - private static final String MODIFIERS_FIELD_NAME = "modifiers"; - private static final int EXPECT_LENGTH = 4; @Override @@ -115,16 +106,7 @@ private Map> getHeaders(Map> hea } private void setHeaders(Request request, Map> headers) { - try { - Field field = request.getClass().getDeclaredField("headers"); - - // 去掉final - Field modifiersField = Field.class.getDeclaredField(MODIFIERS_FIELD_NAME); - ReflectUtils.getAccessibleObject(modifiersField).setInt(field, field.getModifiers() & ~Modifier.FINAL); - ReflectUtils.getAccessibleObject(field).set(request, headers); - } catch (IllegalAccessException | NoSuchFieldException e) { - LOGGER.log(Level.WARNING, "Fail to set the headers.", e); - } + com.huaweicloud.sermant.core.utils.ReflectUtils.setFieldValue(request, "headers", headers); } private Optional getRequestHeader() { diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/HystrixActionInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/HystrixActionInterceptor.java index aeb70e07b6..4329bc97f9 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/HystrixActionInterceptor.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/HystrixActionInterceptor.java @@ -25,6 +25,8 @@ import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext; import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableDefault; +import java.util.Collections; + /** * HystrixContexSchedulerAction增强类,设置线程参数 * @@ -32,6 +34,8 @@ * @since 2022-07-12 */ public class HystrixActionInterceptor extends AbstractInterceptor { + private static final RequestHeader EMPTY_REQUEST_HEADER = new RequestHeader(Collections.emptyMap()); + @Override public ExecuteContext before(ExecuteContext context) { Object[] arguments = context.getArguments(); @@ -40,7 +44,10 @@ public ExecuteContext before(ExecuteContext context) { HystrixRequestContext.initializeContext(); } HystrixRequestVariableDefault hystrixRequest = new HystrixRequestVariableDefault<>(); - hystrixRequest.set(ThreadLocalUtils.getRequestHeader()); + RequestHeader requestHeader = ThreadLocalUtils.getRequestHeader(); + + // 禁止存入null,否则会有严重的性能问题 + hystrixRequest.set(requestHeader == null ? EMPTY_REQUEST_HEADER : requestHeader); } return context; } diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/RouteHandlerInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/RouteHandlerInterceptor.java index aca8548ac8..8b85d60700 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/RouteHandlerInterceptor.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/RouteHandlerInterceptor.java @@ -18,6 +18,7 @@ import com.huaweicloud.sermant.core.service.ServiceManager; import com.huaweicloud.sermant.router.common.request.RequestHeader; +import com.huaweicloud.sermant.router.common.utils.CollectionUtils; import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; import com.huaweicloud.sermant.router.spring.service.SpringConfigService; @@ -55,9 +56,12 @@ public RouteHandlerInterceptor() { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) { - Map> header = new HashMap<>(); Set matchKeys = configService.getMatchKeys(); + if (CollectionUtils.isEmpty(matchKeys)) { + return true; + } Collection headerNames = enumeration2Collection(request.getHeaderNames(), false); + Map> header = new HashMap<>(); for (String headerKey : matchKeys) { if (headerNames.contains(headerKey)) { header.put(headerKey, (List) enumeration2Collection(request.getHeaders(headerKey), true)); diff --git a/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/service/LoadBalancerServiceImpl.java b/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/service/LoadBalancerServiceImpl.java index 9b25345329..eb54b823f0 100644 --- a/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/service/LoadBalancerServiceImpl.java +++ b/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/service/LoadBalancerServiceImpl.java @@ -100,7 +100,8 @@ private List getTargetInstancesByRules(String targetName, List i if (!CollectionUtils.isEmpty(routes)) { return RuleStrategyHandler.INSTANCE.getMatchInstances(targetName, instances, routes); } - return RuleStrategyHandler.INSTANCE.getMismatchInstances(targetName, instances, RuleUtils.getTags(rules), true); + return RuleStrategyHandler.INSTANCE + .getMismatchInstances(targetName, instances, RuleUtils.getTags(rules, false), true); } private List getTargetInstancesByRequest(String targetName, List instances, diff --git a/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandler.java b/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandler.java index 10f0c4c6e6..4a46809ddc 100644 --- a/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandler.java +++ b/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandler.java @@ -68,7 +68,7 @@ private void init(AbstractMetadataMapper mapper) { * @return 路由匹配的实例 */ public List getMatchInstances(String serviceName, List instances, List routes) { - return getRuleStrategy(instances).getMatchInstances(serviceName, instances, routes); + return getRuleStrategy(instances).getMatchInstances(serviceName, instances, routes, false); } /** @@ -123,6 +123,6 @@ private AbstractRuleStrategy getRuleStrategy(List instances) { } private AbstractMetadataMapper getMetadataMapper(Object obj) { - return map.getOrDefault(obj.getClass().getCanonicalName(), defaultMetadataMapper); + return map.getOrDefault(obj.getClass().getName(), defaultMetadataMapper); } } \ No newline at end of file