diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowChecker.java b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowChecker.java index b61c2491..aa4598f8 100644 --- a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowChecker.java +++ b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowChecker.java @@ -43,9 +43,9 @@ import com.alibaba.csp.sentinel.util.TimeUtil; * @author Eric Zhao * @since 0.2.0 */ -final class ParamFlowChecker { +public final class ParamFlowChecker { - static boolean passCheck(ResourceWrapper resourceWrapper, /*@Valid*/ ParamFlowRule rule, /*@Valid*/ int count, + public static boolean passCheck(ResourceWrapper resourceWrapper, /*@Valid*/ ParamFlowRule rule, /*@Valid*/ int count, Object... args) { if (args == null) { return true; @@ -249,7 +249,7 @@ final class ParamFlowChecker { private static ParameterMetric getParameterMetric(ResourceWrapper resourceWrapper) { // Should not be null. - return ParamFlowSlot.getParamMetric(resourceWrapper); + return ParameterMetricStorage.getParamMetric(resourceWrapper); } @SuppressWarnings("unchecked") diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleManager.java b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleManager.java index 2481c943..2467ba64 100644 --- a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleManager.java +++ b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleManager.java @@ -16,7 +16,6 @@ package com.alibaba.csp.sentinel.slots.block.flow.param; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -26,9 +25,7 @@ import com.alibaba.csp.sentinel.log.RecordLog; import com.alibaba.csp.sentinel.property.DynamicSentinelProperty; import com.alibaba.csp.sentinel.property.PropertyListener; import com.alibaba.csp.sentinel.property.SentinelProperty; -import com.alibaba.csp.sentinel.slots.block.RuleConstant; import com.alibaba.csp.sentinel.util.AssertUtil; -import com.alibaba.csp.sentinel.util.StringUtil; /** * Manager for frequent ("hot-spot") parameter flow rules. @@ -39,7 +36,7 @@ import com.alibaba.csp.sentinel.util.StringUtil; */ public final class ParamFlowRuleManager { - private static final Map> paramFlowRules = new ConcurrentHashMap<>(); + private static final Map> paramFlowRules = new ConcurrentHashMap<>(); private final static RulePropertyListener PROPERTY_LISTENER = new RulePropertyListener(); private static SentinelProperty> currentProperty = new DynamicSentinelProperty<>(); @@ -83,7 +80,7 @@ public final class ParamFlowRuleManager { } public static boolean hasRules(String resourceName) { - Set rules = paramFlowRules.get(resourceName); + List rules = paramFlowRules.get(resourceName); return rules != null && !rules.isEmpty(); } @@ -94,7 +91,7 @@ public final class ParamFlowRuleManager { */ public static List getRules() { List rules = new ArrayList<>(); - for (Map.Entry> entry : paramFlowRules.entrySet()) { + for (Map.Entry> entry : paramFlowRules.entrySet()) { rules.addAll(entry.getValue()); } return rules; @@ -104,61 +101,38 @@ public final class ParamFlowRuleManager { @Override public void configUpdate(List list) { - Map> rules = aggregateHotParamRules(list); + Map> rules = aggregateAndPrepareParamRules(list); if (rules != null) { paramFlowRules.clear(); paramFlowRules.putAll(rules); } - RecordLog.info("[ParamFlowRuleManager] Hot spot parameter flow rules received: " + paramFlowRules); + RecordLog.info("[ParamFlowRuleManager] Parameter flow rules received: " + paramFlowRules); } @Override public void configLoad(List list) { - Map> rules = aggregateHotParamRules(list); + Map> rules = aggregateAndPrepareParamRules(list); if (rules != null) { paramFlowRules.clear(); paramFlowRules.putAll(rules); } - RecordLog.info("[ParamFlowRuleManager] Hot spot parameter flow rules received: " + paramFlowRules); + RecordLog.info("[ParamFlowRuleManager] Parameter flow rules received: " + paramFlowRules); } - private Map> aggregateHotParamRules(List list) { - Map> newRuleMap = new ConcurrentHashMap<>(); - - if (list == null || list.isEmpty()) { + private Map> aggregateAndPrepareParamRules(List list) { + Map> newRuleMap = ParamFlowRuleUtil.buildParamRuleMap(list); + if (newRuleMap == null || newRuleMap.isEmpty()) { // No parameter flow rules, so clear all the metrics. - ParamFlowSlot.getMetricsMap().clear(); + ParameterMetricStorage.getMetricsMap().clear(); RecordLog.info("[ParamFlowRuleManager] No parameter flow rules, clearing all parameter metrics"); return newRuleMap; } - for (ParamFlowRule rule : list) { - if (!ParamFlowRuleUtil.isValidRule(rule)) { - RecordLog.warn("[ParamFlowRuleManager] Ignoring invalid rule when loading new rules: " + rule); - continue; - } - - if (StringUtil.isBlank(rule.getLimitApp())) { - rule.setLimitApp(RuleConstant.LIMIT_APP_DEFAULT); - } - - ParamFlowRuleUtil.fillExceptionFlowItems(rule); - - String resourceName = rule.getResource(); - Set ruleSet = newRuleMap.get(resourceName); - if (ruleSet == null) { - ruleSet = new HashSet<>(); - newRuleMap.put(resourceName, ruleSet); - } - - ruleSet.add(rule); - } - - // Clear unused hot param metrics. + // Clear unused parameter metrics. Set previousResources = paramFlowRules.keySet(); for (String resource : previousResources) { if (!newRuleMap.containsKey(resource)) { - ParamFlowSlot.clearHotParamMetricForName(resource); + ParameterMetricStorage.clearParamMetricForResource(resource); } } @@ -166,6 +140,5 @@ public final class ParamFlowRuleManager { } } - private ParamFlowRuleManager() { - } + private ParamFlowRuleManager() {} } diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleUtil.java b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleUtil.java index a8809a15..dd4c1207 100644 --- a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleUtil.java +++ b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleUtil.java @@ -17,18 +17,32 @@ package com.alibaba.csp.sentinel.slots.block.flow.param; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import com.alibaba.csp.sentinel.log.RecordLog; +import com.alibaba.csp.sentinel.slots.block.RuleConstant; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleUtil; +import com.alibaba.csp.sentinel.util.AssertUtil; import com.alibaba.csp.sentinel.util.StringUtil; +import com.alibaba.csp.sentinel.util.function.Function; +import com.alibaba.csp.sentinel.util.function.Predicate; /** * @author Eric Zhao */ public final class ParamFlowRuleUtil { + /** + * Check whether the provided rule is valid. + * + * @param rule any parameter rule + * @return true if valid, otherwise false + */ public static boolean isValidRule(ParamFlowRule rule) { return rule != null && !StringUtil.isBlank(rule.getResource()) && rule.getCount() >= 0 && rule.getGrade() >= 0 && rule.getParamIdx() != null @@ -55,6 +69,11 @@ public final class ParamFlowRuleUtil { return id != null && id > 0; } + /** + * Fill the parameter rule with parsed items. + * + * @param rule valid parameter rule + */ public static void fillExceptionFlowItems(ParamFlowRule rule) { if (rule != null) { if (rule.getParamFlowItemList() == null) { @@ -66,11 +85,111 @@ public final class ParamFlowRuleUtil { } } + /** + * Build the flow rule map from raw list of flow rules, grouping by resource name. + * + * @param list raw list of flow rules + * @return constructed new flow rule map; empty map if list is null or empty, or no valid rules + * @since 1.6.1 + */ + public static Map> buildParamRuleMap(List list) { + return buildParamRuleMap(list, null); + } + + /** + * Build the parameter flow rule map from raw list of rules, grouping by resource name. + * + * @param list raw list of parameter flow rules + * @param filter rule filter + * @return constructed new parameter flow rule map; empty map if list is null or empty, or no wanted rules + * @since 1.6.1 + */ + public static Map> buildParamRuleMap(List list, + Predicate filter) { + return buildParamRuleMap(list, filter, true); + } + + /** + * Build the parameter flow rule map from raw list of rules, grouping by resource name. + * + * @param list raw list of parameter flow rules + * @param filter rule filter + * @param shouldSort whether the rules should be sorted + * @return constructed new parameter flow rule map; empty map if list is null or empty, or no wanted rules + * @since 1.6.1 + */ + public static Map> buildParamRuleMap(List list, + Predicate filter, + boolean shouldSort) { + return buildParamRuleMap(list, EXTRACT_RESOURCE, filter, shouldSort); + } + + /** + * Build the rule map from raw list of parameter flow rules, grouping by provided group function. + * + * @param list raw list of parameter flow rules + * @param groupFunction grouping function of the map (by key) + * @param filter rule filter + * @param shouldSort whether the rules should be sorted + * @param type of key + * @return constructed new rule map; empty map if list is null or empty, or no wanted rules + * @since 1.6.1 + */ + public static Map> buildParamRuleMap(List list, + Function groupFunction, + Predicate filter, + boolean shouldSort) { + AssertUtil.notNull(groupFunction, "groupFunction should not be null"); + Map> newRuleMap = new ConcurrentHashMap<>(); + if (list == null || list.isEmpty()) { + return newRuleMap; + } + Map> tmpMap = new ConcurrentHashMap<>(); + + for (ParamFlowRule rule : list) { + if (!ParamFlowRuleUtil.isValidRule(rule)) { + RecordLog.warn("[ParamFlowRuleManager] Ignoring invalid rule when loading new rules: " + rule); + continue; + } + if (filter != null && !filter.test(rule)) { + continue; + } + if (StringUtil.isBlank(rule.getLimitApp())) { + rule.setLimitApp(RuleConstant.LIMIT_APP_DEFAULT); + } + + ParamFlowRuleUtil.fillExceptionFlowItems(rule); + + K key = groupFunction.apply(rule); + if (key == null) { + continue; + } + Set flowRules = tmpMap.get(key); + + if (flowRules == null) { + // Use hash set here to remove duplicate rules. + flowRules = new HashSet<>(); + tmpMap.put(key, flowRules); + } + + flowRules.add(rule); + } + for (Entry> entries : tmpMap.entrySet()) { + List rules = new ArrayList<>(entries.getValue()); + if (shouldSort) { + // TODO: Sort the rules. + } + newRuleMap.put(entries.getKey(), rules); + } + + return newRuleMap; + } + static Map parseHotItems(List items) { - Map itemMap = new HashMap(); if (items == null || items.isEmpty()) { - return itemMap; + return new HashMap<>(); } + Map itemMap = new HashMap<>(items.size()); for (ParamFlowItem item : items) { // Value should not be null. Object value; @@ -120,5 +239,12 @@ public final class ParamFlowRuleUtil { return value; } + private static final Function EXTRACT_RESOURCE = new Function() { + @Override + public String apply(ParamFlowRule rule) { + return rule.getResource(); + } + }; + private ParamFlowRuleUtil() {} } diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowSlot.java b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowSlot.java index 001f7d3f..7da682cf 100644 --- a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowSlot.java +++ b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowSlot.java @@ -16,18 +16,12 @@ package com.alibaba.csp.sentinel.slots.block.flow.param; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import com.alibaba.csp.sentinel.EntryType; import com.alibaba.csp.sentinel.context.Context; -import com.alibaba.csp.sentinel.log.RecordLog; import com.alibaba.csp.sentinel.node.DefaultNode; import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot; import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; -import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper; import com.alibaba.csp.sentinel.slots.block.BlockException; -import com.alibaba.csp.sentinel.util.StringUtil; /** * A processor slot that is responsible for flow control by frequent ("hot spot") parameters. @@ -38,13 +32,6 @@ import com.alibaba.csp.sentinel.util.StringUtil; */ public class ParamFlowSlot extends AbstractLinkedProcessorSlot { - private static final Map metricsMap = new ConcurrentHashMap<>(); - - /** - * Lock for a specific resource. - */ - private final Object LOCK = new Object(); - @Override public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... args) throws Throwable { @@ -68,7 +55,7 @@ public class ParamFlowSlot extends AbstractLinkedProcessorSlot { if (-paramIdx <= length) { rule.setParamIdx(length + paramIdx); } else { - // illegal index, give it a illegal positive value, latter rule check will pass + // Illegal index, give it a illegal positive value, latter rule checking will pass. rule.setParamIdx(-paramIdx); } } @@ -87,7 +74,7 @@ public class ParamFlowSlot extends AbstractLinkedProcessorSlot { applyRealParamIdx(rule, args.length); // Initialize the parameter metrics. - initHotParamMetricsFor(resourceWrapper, rule); + ParameterMetricStorage.initParamMetricsFor(resourceWrapper, rule); if (!ParamFlowChecker.passCheck(resourceWrapper, rule, count, args)) { String triggeredParam = ""; @@ -99,60 +86,4 @@ public class ParamFlowSlot extends AbstractLinkedProcessorSlot { } } } - - /** - * Init the parameter metric and index map for given resource. - * Package-private for test. - * - * @param resourceWrapper resource to init - * @param rule relevant rule - */ - void initHotParamMetricsFor(ResourceWrapper resourceWrapper, /*@Valid*/ ParamFlowRule rule) { - ParameterMetric metric; - // Assume that the resource is valid. - if ((metric = metricsMap.get(resourceWrapper)) == null) { - synchronized (LOCK) { - if ((metric = metricsMap.get(resourceWrapper)) == null) { - metric = new ParameterMetric(); - metricsMap.put(resourceWrapper, metric); - RecordLog.info("[ParamFlowSlot] Creating parameter metric for: " + resourceWrapper.getName()); - } - } - } - metric.initialize(rule); - } - - public static ParameterMetric getParamMetric(ResourceWrapper resourceWrapper) { - if (resourceWrapper == null || resourceWrapper.getName() == null) { - return null; - } - return metricsMap.get(resourceWrapper); - } - - public static ParameterMetric getHotParamMetricForName(String resourceName) { - if (StringUtil.isBlank(resourceName)) { - return null; - } - for (EntryType nodeType : EntryType.values()) { - ParameterMetric metric = metricsMap.get(new StringResourceWrapper(resourceName, nodeType)); - if (metric != null) { - return metric; - } - } - return null; - } - - static void clearHotParamMetricForName(String resourceName) { - if (StringUtil.isBlank(resourceName)) { - return; - } - for (EntryType nodeType : EntryType.values()) { - metricsMap.remove(new StringResourceWrapper(resourceName, nodeType)); - } - RecordLog.info("[ParamFlowSlot] Clearing parameter metric for: " + resourceName); - } - - static Map getMetricsMap() { - return metricsMap; - } } diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParameterMetricStorage.java b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParameterMetricStorage.java new file mode 100644 index 00000000..5b531bfa --- /dev/null +++ b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParameterMetricStorage.java @@ -0,0 +1,91 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.slots.block.flow.param; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.csp.sentinel.log.RecordLog; +import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; +import com.alibaba.csp.sentinel.util.StringUtil; + +/** + * @author Eric Zhao + * @since 1.6.1 + */ +public final class ParameterMetricStorage { + + private static final Map metricsMap = new ConcurrentHashMap<>(); + + /** + * Lock for a specific resource. + */ + private static final Object LOCK = new Object(); + + /** + * Init the parameter metric and index map for given resource. + * Package-private for test. + * + * @param resourceWrapper resource to init + * @param rule relevant rule + */ + public static void initParamMetricsFor(ResourceWrapper resourceWrapper, /*@Valid*/ ParamFlowRule rule) { + if (resourceWrapper == null || resourceWrapper.getName() == null) { + return; + } + String resourceName = resourceWrapper.getName(); + ParameterMetric metric; + // Assume that the resource is valid. + if ((metric = metricsMap.get(resourceName)) == null) { + synchronized (LOCK) { + if ((metric = metricsMap.get(resourceName)) == null) { + metric = new ParameterMetric(); + metricsMap.put(resourceWrapper.getName(), metric); + RecordLog.info("[ParameterMetricStorage] Creating parameter metric for: " + resourceWrapper.getName()); + } + } + } + metric.initialize(rule); + } + + public static ParameterMetric getParamMetric(ResourceWrapper resourceWrapper) { + if (resourceWrapper == null || resourceWrapper.getName() == null) { + return null; + } + return metricsMap.get(resourceWrapper.getName()); + } + + public static ParameterMetric getParamMetricForResource(String resourceName) { + if (resourceName == null) { + return null; + } + return metricsMap.get(resourceName); + } + + public static void clearParamMetricForResource(String resourceName) { + if (StringUtil.isBlank(resourceName)) { + return; + } + metricsMap.remove(resourceName); + RecordLog.info("[ParameterMetricStorage] Clearing parameter metric for: " + resourceName); + } + + static Map getMetricsMap() { + return metricsMap; + } + + private ParameterMetricStorage() {} +} diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/statistic/ParamFlowStatisticEntryCallback.java b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/statistic/ParamFlowStatisticEntryCallback.java index b7c09d81..50073ec9 100644 --- a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/statistic/ParamFlowStatisticEntryCallback.java +++ b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/statistic/ParamFlowStatisticEntryCallback.java @@ -20,8 +20,8 @@ import com.alibaba.csp.sentinel.node.DefaultNode; import com.alibaba.csp.sentinel.slotchain.ProcessorSlotEntryCallback; import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; import com.alibaba.csp.sentinel.slots.block.BlockException; -import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowSlot; import com.alibaba.csp.sentinel.slots.block.flow.param.ParameterMetric; +import com.alibaba.csp.sentinel.slots.block.flow.param.ParameterMetricStorage; /** * @author Eric Zhao @@ -32,7 +32,7 @@ public class ParamFlowStatisticEntryCallback implements ProcessorSlotEntryCallba @Override public void onPass(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, Object... args) { // The "hot spot" parameter metric is present only if parameter flow rules for the resource exist. - ParameterMetric parameterMetric = ParamFlowSlot.getParamMetric(resourceWrapper); + ParameterMetric parameterMetric = ParameterMetricStorage.getParamMetric(resourceWrapper); if (parameterMetric != null) { parameterMetric.addThreadCount(args); diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/statistic/ParamFlowStatisticExitCallback.java b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/statistic/ParamFlowStatisticExitCallback.java index 1cb63917..d3446ff5 100644 --- a/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/statistic/ParamFlowStatisticExitCallback.java +++ b/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/statistic/ParamFlowStatisticExitCallback.java @@ -18,8 +18,8 @@ package com.alibaba.csp.sentinel.slots.statistic; import com.alibaba.csp.sentinel.context.Context; import com.alibaba.csp.sentinel.slotchain.ProcessorSlotExitCallback; import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; -import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowSlot; import com.alibaba.csp.sentinel.slots.block.flow.param.ParameterMetric; +import com.alibaba.csp.sentinel.slots.block.flow.param.ParameterMetricStorage; /** * @author Eric Zhao @@ -30,7 +30,7 @@ public class ParamFlowStatisticExitCallback implements ProcessorSlotExitCallback @Override public void onExit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) { if (context.getCurEntry().getError() == null) { - ParameterMetric parameterMetric = ParamFlowSlot.getParamMetric(resourceWrapper); + ParameterMetric parameterMetric = ParameterMetricStorage.getParamMetric(resourceWrapper); if (parameterMetric != null) { parameterMetric.decreaseThreadCount(args); diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowCheckerTest.java b/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowCheckerTest.java index 628b859f..70c549f2 100644 --- a/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowCheckerTest.java +++ b/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowCheckerTest.java @@ -90,7 +90,7 @@ public class ParamFlowCheckerTest { rule.setParsedHotItems(map); ParameterMetric metric = new ParameterMetric(); - ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric); + ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric); metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA)); @@ -127,7 +127,7 @@ public class ParamFlowCheckerTest { when(metric.getThreadCount(paramIdx, valueB)).thenReturn(globalThreshold - 1); when(metric.getThreadCount(paramIdx, valueC)).thenReturn(globalThreshold - 1); when(metric.getThreadCount(paramIdx, valueD)).thenReturn(globalThreshold + 1); - ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric); + ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric); assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA)); assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueB)); @@ -158,7 +158,7 @@ public class ParamFlowCheckerTest { String v1 = "a", v2 = "B", v3 = "Cc"; List list = Arrays.asList(v1, v2, v3); ParameterMetric metric = new ParameterMetric(); - ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric); + ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric); metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); metric.getRuleTokenCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); @@ -181,7 +181,7 @@ public class ParamFlowCheckerTest { String v1 = "a", v2 = "B", v3 = "Cc"; Object arr = new String[] {v1, v2, v3}; ParameterMetric metric = new ParameterMetric(); - ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric); + ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric); metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); assertTrue(ParamFlowChecker.passCheck(resourceWrapper, rule, 1, arr)); @@ -190,11 +190,11 @@ public class ParamFlowCheckerTest { @Before public void setUp() throws Exception { - ParamFlowSlot.getMetricsMap().clear(); + ParameterMetricStorage.getMetricsMap().clear(); } @After public void tearDown() throws Exception { - ParamFlowSlot.getMetricsMap().clear(); + ParameterMetricStorage.getMetricsMap().clear(); } } \ No newline at end of file diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowDefaultCheckerTest.java b/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowDefaultCheckerTest.java index f28bd1c0..fca4fb1c 100644 --- a/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowDefaultCheckerTest.java +++ b/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowDefaultCheckerTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.slots.block.flow.param; import static org.junit.Assert.assertEquals; @@ -41,7 +56,7 @@ public class ParamFlowDefaultCheckerTest extends AbstractTimeBasedTest { String valueA = "valueA"; ParameterMetric metric = new ParameterMetric(); - ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric); + ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric); metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); metric.getRuleTokenCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); @@ -81,7 +96,7 @@ public class ParamFlowDefaultCheckerTest extends AbstractTimeBasedTest { String valueA = "valueA"; ParameterMetric metric = new ParameterMetric(); - ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric); + ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric); metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); metric.getRuleTokenCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); @@ -151,7 +166,7 @@ public class ParamFlowDefaultCheckerTest extends AbstractTimeBasedTest { String valueA = "helloWorld"; ParameterMetric metric = new ParameterMetric(); - ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric); + ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric); metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); metric.getRuleTokenCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); @@ -204,7 +219,7 @@ public class ParamFlowDefaultCheckerTest extends AbstractTimeBasedTest { final String valueA = "valueA"; ParameterMetric metric = new ParameterMetric(); - ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric); + ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric); metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); metric.getRuleTokenCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); @@ -270,11 +285,11 @@ public class ParamFlowDefaultCheckerTest extends AbstractTimeBasedTest { @Before public void setUp() throws Exception { - ParamFlowSlot.getMetricsMap().clear(); + ParameterMetricStorage.getMetricsMap().clear(); } @After public void tearDown() throws Exception { - ParamFlowSlot.getMetricsMap().clear(); + ParameterMetricStorage.getMetricsMap().clear(); } } diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleManagerTest.java b/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleManagerTest.java index 58af6358..8241517b 100644 --- a/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleManagerTest.java +++ b/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleManagerTest.java @@ -19,8 +19,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import com.alibaba.csp.sentinel.EntryType; -import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper; import com.alibaba.csp.sentinel.slots.block.RuleConstant; import org.junit.After; @@ -40,33 +38,36 @@ public class ParamFlowRuleManagerTest { @Before public void setUp() { ParamFlowRuleManager.loadRules(null); + ParameterMetricStorage.getMetricsMap().clear(); } @After public void tearDown() { ParamFlowRuleManager.loadRules(null); + ParameterMetricStorage.getMetricsMap().clear(); } @Test - public void testLoadHotParamRulesClearingUnusedMetrics() { + public void testLoadParamRulesClearingUnusedMetrics() { final String resA = "resA"; ParamFlowRule ruleA = new ParamFlowRule(resA) .setCount(1) .setParamIdx(0); ParamFlowRuleManager.loadRules(Collections.singletonList(ruleA)); - ParamFlowSlot.getMetricsMap().put(new StringResourceWrapper(resA, EntryType.IN), new ParameterMetric()); - assertNotNull(ParamFlowSlot.getHotParamMetricForName(resA)); + ParameterMetricStorage.getMetricsMap().put(resA, new ParameterMetric()); + assertNotNull(ParameterMetricStorage.getParamMetricForResource(resA)); final String resB = "resB"; ParamFlowRule ruleB = new ParamFlowRule(resB) .setCount(2) .setParamIdx(1); ParamFlowRuleManager.loadRules(Collections.singletonList(ruleB)); - assertNull("The unused hot param metric should be cleared", ParamFlowSlot.getHotParamMetricForName(resA)); + assertNull("The unused hot param metric should be cleared", + ParameterMetricStorage.getParamMetricForResource(resA)); } @Test - public void testLoadHotParamRulesAndGet() { + public void testLoadParamRulesAndGet() { final String resA = "abc"; final String resB = "foo"; final String resC = "baz"; @@ -107,4 +108,4 @@ public class ParamFlowRuleManagerTest { assertTrue(allRules.contains(ruleC)); assertTrue(allRules.contains(ruleD)); } -} \ No newline at end of file +} diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowSlotTest.java b/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowSlotTest.java index df59432b..0d983844 100644 --- a/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowSlotTest.java +++ b/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowSlotTest.java @@ -82,7 +82,7 @@ public class ParamFlowSlotTest { ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN); paramFlowSlot.entry(null, resourceWrapper, null, 1, false, "abc"); // The parameter metric instance will not be created. - assertNull(ParamFlowSlot.getParamMetric(resourceWrapper)); + assertNull(ParameterMetricStorage.getParamMetric(resourceWrapper)); } @Test @@ -106,7 +106,7 @@ public class ParamFlowSlotTest { map.put(argToGo, new AtomicLong(TimeUtil.currentTimeMillis())); // Insert the mock metric to control pass or block. - ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric); + ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric); // The first entry will pass. paramFlowSlot.entry(null, resourceWrapper, null, 1, false, argToGo); @@ -121,48 +121,16 @@ public class ParamFlowSlotTest { fail("The second entry should be blocked"); } - @Test - public void testGetNullParamMetric() { - assertNull(ParamFlowSlot.getParamMetric(null)); - } - - @Test - public void testInitParamMetrics() { - - ParamFlowRule rule = new ParamFlowRule(); - rule.setParamIdx(1); - int index = 1; - String resourceName = "res-" + System.currentTimeMillis(); - ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN); - - assertNull(ParamFlowSlot.getParamMetric(resourceWrapper)); - - paramFlowSlot.initHotParamMetricsFor(resourceWrapper, rule); - ParameterMetric metric = ParamFlowSlot.getParamMetric(resourceWrapper); - assertNotNull(metric); - assertNotNull(metric.getRuleTimeCounterMap().get(rule)); - assertNotNull(metric.getThreadCountMap().get(index)); - - // Duplicate init. - paramFlowSlot.initHotParamMetricsFor(resourceWrapper, rule); - assertSame(metric, ParamFlowSlot.getParamMetric(resourceWrapper)); - - ParamFlowRule rule2 = new ParamFlowRule(); - rule2.setParamIdx(1); - assertSame(metric, ParamFlowSlot.getParamMetric(resourceWrapper)); - - } - @Before - public void setUp() throws Exception { + public void setUp() { ParamFlowRuleManager.loadRules(null); - ParamFlowSlot.getMetricsMap().clear(); + ParameterMetricStorage.getMetricsMap().clear(); } @After - public void tearDown() throws Exception { + public void tearDown() { // Clean the metrics map. - ParamFlowSlot.getMetricsMap().clear(); ParamFlowRuleManager.loadRules(null); + ParameterMetricStorage.getMetricsMap().clear(); } -} \ No newline at end of file +} diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowThrottleRateLimitingCheckerTest.java b/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowThrottleRateLimitingCheckerTest.java index 2f2fc3f8..8d9cfde4 100644 --- a/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowThrottleRateLimitingCheckerTest.java +++ b/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowThrottleRateLimitingCheckerTest.java @@ -1,7 +1,20 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.slots.block.flow.param; -import static org.junit.Assert.assertEquals; - import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -19,6 +32,8 @@ import com.alibaba.csp.sentinel.slots.block.RuleConstant; import com.alibaba.csp.sentinel.slots.statistic.cache.ConcurrentLinkedHashMapWrapper; import com.alibaba.csp.sentinel.util.TimeUtil; +import static org.junit.Assert.assertEquals; + /** * @author jialiang.linjl */ @@ -41,7 +56,7 @@ public class ParamFlowThrottleRateLimitingCheckerTest { String valueA = "valueA"; ParameterMetric metric = new ParameterMetric(); - ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric); + ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric); metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); long currentTime = TimeUtil.currentTimeMillis(); @@ -85,7 +100,7 @@ public class ParamFlowThrottleRateLimitingCheckerTest { final String valueA = "valueA"; ParameterMetric metric = new ParameterMetric(); - ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric); + ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric); metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper(4000)); int threadCount = 40; @@ -154,11 +169,11 @@ public class ParamFlowThrottleRateLimitingCheckerTest { @Before public void setUp() throws Exception { - ParamFlowSlot.getMetricsMap().clear(); + ParameterMetricStorage.getMetricsMap().clear(); } @After public void tearDown() throws Exception { - ParamFlowSlot.getMetricsMap().clear(); + ParameterMetricStorage.getMetricsMap().clear(); } } diff --git a/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParameterMetricStorageTest.java b/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParameterMetricStorageTest.java new file mode 100644 index 00000000..ba2fd75b --- /dev/null +++ b/sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParameterMetricStorageTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://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 com.alibaba.csp.sentinel.slots.block.flow.param; + +import com.alibaba.csp.sentinel.EntryType; +import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; +import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author Eric Zhao + */ +public class ParameterMetricStorageTest { + + @Test + public void testGetNullParamMetric() { + assertNull(ParameterMetricStorage.getParamMetric(null)); + } + + @Test + public void testInitParamMetrics() { + ParamFlowRule rule = new ParamFlowRule(); + rule.setParamIdx(1); + int index = 1; + String resourceName = "res-" + System.currentTimeMillis(); + ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN); + + assertNull(ParameterMetricStorage.getParamMetric(resourceWrapper)); + + ParameterMetricStorage.initParamMetricsFor(resourceWrapper, rule); + ParameterMetric metric = ParameterMetricStorage.getParamMetric(resourceWrapper); + assertNotNull(metric); + assertNotNull(metric.getRuleTimeCounterMap().get(rule)); + assertNotNull(metric.getThreadCountMap().get(index)); + + // Duplicate init. + ParameterMetricStorage.initParamMetricsFor(resourceWrapper, rule); + assertSame(metric, ParameterMetricStorage.getParamMetric(resourceWrapper)); + + ParamFlowRule rule2 = new ParamFlowRule(); + rule2.setParamIdx(1); + assertSame(metric, ParameterMetricStorage.getParamMetric(resourceWrapper)); + } + + @Before + public void setUp() { + ParameterMetricStorage.getMetricsMap().clear(); + } + + @After + public void tearDown() { + ParameterMetricStorage.getMetricsMap().clear(); + } +}