Separate parameter metric storage from ParamFlowSlot and improve ParamFlowRuleUtil
- Add a ParameterMetricStorage specific for caching ParameterMetric (moved from ParamSlot) - Add rule map building helper method in ParamFlowRuleUtil so that we can reuse it in other rule managers Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
parent
54da16d304
commit
77dec5f845
|
|
@ -43,9 +43,9 @@ import com.alibaba.csp.sentinel.util.TimeUtil;
|
||||||
* @author Eric Zhao
|
* @author Eric Zhao
|
||||||
* @since 0.2.0
|
* @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) {
|
Object... args) {
|
||||||
if (args == null) {
|
if (args == null) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -249,7 +249,7 @@ final class ParamFlowChecker {
|
||||||
|
|
||||||
private static ParameterMetric getParameterMetric(ResourceWrapper resourceWrapper) {
|
private static ParameterMetric getParameterMetric(ResourceWrapper resourceWrapper) {
|
||||||
// Should not be null.
|
// Should not be null.
|
||||||
return ParamFlowSlot.getParamMetric(resourceWrapper);
|
return ParameterMetricStorage.getParamMetric(resourceWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
package com.alibaba.csp.sentinel.slots.block.flow.param;
|
package com.alibaba.csp.sentinel.slots.block.flow.param;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
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.DynamicSentinelProperty;
|
||||||
import com.alibaba.csp.sentinel.property.PropertyListener;
|
import com.alibaba.csp.sentinel.property.PropertyListener;
|
||||||
import com.alibaba.csp.sentinel.property.SentinelProperty;
|
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.AssertUtil;
|
||||||
import com.alibaba.csp.sentinel.util.StringUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manager for frequent ("hot-spot") parameter flow rules.
|
* Manager for frequent ("hot-spot") parameter flow rules.
|
||||||
|
|
@ -39,7 +36,7 @@ import com.alibaba.csp.sentinel.util.StringUtil;
|
||||||
*/
|
*/
|
||||||
public final class ParamFlowRuleManager {
|
public final class ParamFlowRuleManager {
|
||||||
|
|
||||||
private static final Map<String, Set<ParamFlowRule>> paramFlowRules = new ConcurrentHashMap<>();
|
private static final Map<String, List<ParamFlowRule>> paramFlowRules = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final static RulePropertyListener PROPERTY_LISTENER = new RulePropertyListener();
|
private final static RulePropertyListener PROPERTY_LISTENER = new RulePropertyListener();
|
||||||
private static SentinelProperty<List<ParamFlowRule>> currentProperty = new DynamicSentinelProperty<>();
|
private static SentinelProperty<List<ParamFlowRule>> currentProperty = new DynamicSentinelProperty<>();
|
||||||
|
|
@ -83,7 +80,7 @@ public final class ParamFlowRuleManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasRules(String resourceName) {
|
public static boolean hasRules(String resourceName) {
|
||||||
Set<ParamFlowRule> rules = paramFlowRules.get(resourceName);
|
List<ParamFlowRule> rules = paramFlowRules.get(resourceName);
|
||||||
return rules != null && !rules.isEmpty();
|
return rules != null && !rules.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,7 +91,7 @@ public final class ParamFlowRuleManager {
|
||||||
*/
|
*/
|
||||||
public static List<ParamFlowRule> getRules() {
|
public static List<ParamFlowRule> getRules() {
|
||||||
List<ParamFlowRule> rules = new ArrayList<>();
|
List<ParamFlowRule> rules = new ArrayList<>();
|
||||||
for (Map.Entry<String, Set<ParamFlowRule>> entry : paramFlowRules.entrySet()) {
|
for (Map.Entry<String, List<ParamFlowRule>> entry : paramFlowRules.entrySet()) {
|
||||||
rules.addAll(entry.getValue());
|
rules.addAll(entry.getValue());
|
||||||
}
|
}
|
||||||
return rules;
|
return rules;
|
||||||
|
|
@ -104,61 +101,38 @@ public final class ParamFlowRuleManager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configUpdate(List<ParamFlowRule> list) {
|
public void configUpdate(List<ParamFlowRule> list) {
|
||||||
Map<String, Set<ParamFlowRule>> rules = aggregateHotParamRules(list);
|
Map<String, List<ParamFlowRule>> rules = aggregateAndPrepareParamRules(list);
|
||||||
if (rules != null) {
|
if (rules != null) {
|
||||||
paramFlowRules.clear();
|
paramFlowRules.clear();
|
||||||
paramFlowRules.putAll(rules);
|
paramFlowRules.putAll(rules);
|
||||||
}
|
}
|
||||||
RecordLog.info("[ParamFlowRuleManager] Hot spot parameter flow rules received: " + paramFlowRules);
|
RecordLog.info("[ParamFlowRuleManager] Parameter flow rules received: " + paramFlowRules);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configLoad(List<ParamFlowRule> list) {
|
public void configLoad(List<ParamFlowRule> list) {
|
||||||
Map<String, Set<ParamFlowRule>> rules = aggregateHotParamRules(list);
|
Map<String, List<ParamFlowRule>> rules = aggregateAndPrepareParamRules(list);
|
||||||
if (rules != null) {
|
if (rules != null) {
|
||||||
paramFlowRules.clear();
|
paramFlowRules.clear();
|
||||||
paramFlowRules.putAll(rules);
|
paramFlowRules.putAll(rules);
|
||||||
}
|
}
|
||||||
RecordLog.info("[ParamFlowRuleManager] Hot spot parameter flow rules received: " + paramFlowRules);
|
RecordLog.info("[ParamFlowRuleManager] Parameter flow rules received: " + paramFlowRules);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Set<ParamFlowRule>> aggregateHotParamRules(List<ParamFlowRule> list) {
|
private Map<String, List<ParamFlowRule>> aggregateAndPrepareParamRules(List<ParamFlowRule> list) {
|
||||||
Map<String, Set<ParamFlowRule>> newRuleMap = new ConcurrentHashMap<>();
|
Map<String, List<ParamFlowRule>> newRuleMap = ParamFlowRuleUtil.buildParamRuleMap(list);
|
||||||
|
if (newRuleMap == null || newRuleMap.isEmpty()) {
|
||||||
if (list == null || list.isEmpty()) {
|
|
||||||
// No parameter flow rules, so clear all the metrics.
|
// 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");
|
RecordLog.info("[ParamFlowRuleManager] No parameter flow rules, clearing all parameter metrics");
|
||||||
return newRuleMap;
|
return newRuleMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ParamFlowRule rule : list) {
|
// Clear unused parameter metrics.
|
||||||
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<ParamFlowRule> ruleSet = newRuleMap.get(resourceName);
|
|
||||||
if (ruleSet == null) {
|
|
||||||
ruleSet = new HashSet<>();
|
|
||||||
newRuleMap.put(resourceName, ruleSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
ruleSet.add(rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear unused hot param metrics.
|
|
||||||
Set<String> previousResources = paramFlowRules.keySet();
|
Set<String> previousResources = paramFlowRules.keySet();
|
||||||
for (String resource : previousResources) {
|
for (String resource : previousResources) {
|
||||||
if (!newRuleMap.containsKey(resource)) {
|
if (!newRuleMap.containsKey(resource)) {
|
||||||
ParamFlowSlot.clearHotParamMetricForName(resource);
|
ParameterMetricStorage.clearParamMetricForResource(resource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,6 +140,5 @@ public final class ParamFlowRuleManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ParamFlowRuleManager() {
|
private ParamFlowRuleManager() {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,18 +17,32 @@ package com.alibaba.csp.sentinel.slots.block.flow.param;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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.log.RecordLog;
|
||||||
|
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
|
||||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleUtil;
|
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.StringUtil;
|
||||||
|
import com.alibaba.csp.sentinel.util.function.Function;
|
||||||
|
import com.alibaba.csp.sentinel.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Eric Zhao
|
* @author Eric Zhao
|
||||||
*/
|
*/
|
||||||
public final class ParamFlowRuleUtil {
|
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) {
|
public static boolean isValidRule(ParamFlowRule rule) {
|
||||||
return rule != null && !StringUtil.isBlank(rule.getResource()) && rule.getCount() >= 0
|
return rule != null && !StringUtil.isBlank(rule.getResource()) && rule.getCount() >= 0
|
||||||
&& rule.getGrade() >= 0 && rule.getParamIdx() != null
|
&& rule.getGrade() >= 0 && rule.getParamIdx() != null
|
||||||
|
|
@ -55,6 +69,11 @@ public final class ParamFlowRuleUtil {
|
||||||
return id != null && id > 0;
|
return id != null && id > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill the parameter rule with parsed items.
|
||||||
|
*
|
||||||
|
* @param rule valid parameter rule
|
||||||
|
*/
|
||||||
public static void fillExceptionFlowItems(ParamFlowRule rule) {
|
public static void fillExceptionFlowItems(ParamFlowRule rule) {
|
||||||
if (rule != null) {
|
if (rule != null) {
|
||||||
if (rule.getParamFlowItemList() == null) {
|
if (rule.getParamFlowItemList() == null) {
|
||||||
|
|
@ -66,11 +85,111 @@ public final class ParamFlowRuleUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Map<Object, Integer> parseHotItems(List<ParamFlowItem> items) {
|
/**
|
||||||
Map<Object, Integer> itemMap = new HashMap<Object, Integer>();
|
* Build the flow rule map from raw list of flow rules, grouping by resource name.
|
||||||
if (items == null || items.isEmpty()) {
|
*
|
||||||
return itemMap;
|
* @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<String, List<ParamFlowRule>> buildParamRuleMap(List<ParamFlowRule> 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<String, List<ParamFlowRule>> buildParamRuleMap(List<ParamFlowRule> list,
|
||||||
|
Predicate<ParamFlowRule> 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<String, List<ParamFlowRule>> buildParamRuleMap(List<ParamFlowRule> list,
|
||||||
|
Predicate<ParamFlowRule> 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 <K> 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 <K> Map<K, List<ParamFlowRule>> buildParamRuleMap(List<ParamFlowRule> list,
|
||||||
|
Function<ParamFlowRule, K> groupFunction,
|
||||||
|
Predicate<ParamFlowRule> filter,
|
||||||
|
boolean shouldSort) {
|
||||||
|
AssertUtil.notNull(groupFunction, "groupFunction should not be null");
|
||||||
|
Map<K, List<ParamFlowRule>> newRuleMap = new ConcurrentHashMap<>();
|
||||||
|
if (list == null || list.isEmpty()) {
|
||||||
|
return newRuleMap;
|
||||||
|
}
|
||||||
|
Map<K, Set<ParamFlowRule>> 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<ParamFlowRule> 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<K, Set<ParamFlowRule>> entries : tmpMap.entrySet()) {
|
||||||
|
List<ParamFlowRule> rules = new ArrayList<>(entries.getValue());
|
||||||
|
if (shouldSort) {
|
||||||
|
// TODO: Sort the rules.
|
||||||
|
}
|
||||||
|
newRuleMap.put(entries.getKey(), rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newRuleMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<Object, Integer> parseHotItems(List<ParamFlowItem> items) {
|
||||||
|
if (items == null || items.isEmpty()) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
Map<Object, Integer> itemMap = new HashMap<>(items.size());
|
||||||
for (ParamFlowItem item : items) {
|
for (ParamFlowItem item : items) {
|
||||||
// Value should not be null.
|
// Value should not be null.
|
||||||
Object value;
|
Object value;
|
||||||
|
|
@ -120,5 +239,12 @@ public final class ParamFlowRuleUtil {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Function<ParamFlowRule, String> EXTRACT_RESOURCE = new Function<ParamFlowRule, String>() {
|
||||||
|
@Override
|
||||||
|
public String apply(ParamFlowRule rule) {
|
||||||
|
return rule.getResource();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private ParamFlowRuleUtil() {}
|
private ParamFlowRuleUtil() {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,18 +16,12 @@
|
||||||
package com.alibaba.csp.sentinel.slots.block.flow.param;
|
package com.alibaba.csp.sentinel.slots.block.flow.param;
|
||||||
|
|
||||||
import java.util.List;
|
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.context.Context;
|
||||||
import com.alibaba.csp.sentinel.log.RecordLog;
|
|
||||||
import com.alibaba.csp.sentinel.node.DefaultNode;
|
import com.alibaba.csp.sentinel.node.DefaultNode;
|
||||||
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot;
|
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot;
|
||||||
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
|
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.slots.block.BlockException;
|
||||||
import com.alibaba.csp.sentinel.util.StringUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A processor slot that is responsible for flow control by frequent ("hot spot") parameters.
|
* 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<DefaultNode> {
|
public class ParamFlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
|
||||||
|
|
||||||
private static final Map<ResourceWrapper, ParameterMetric> metricsMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lock for a specific resource.
|
|
||||||
*/
|
|
||||||
private final Object LOCK = new Object();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,
|
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,
|
||||||
boolean prioritized, Object... args) throws Throwable {
|
boolean prioritized, Object... args) throws Throwable {
|
||||||
|
|
@ -68,7 +55,7 @@ public class ParamFlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
|
||||||
if (-paramIdx <= length) {
|
if (-paramIdx <= length) {
|
||||||
rule.setParamIdx(length + paramIdx);
|
rule.setParamIdx(length + paramIdx);
|
||||||
} else {
|
} 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);
|
rule.setParamIdx(-paramIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +74,7 @@ public class ParamFlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
|
||||||
applyRealParamIdx(rule, args.length);
|
applyRealParamIdx(rule, args.length);
|
||||||
|
|
||||||
// Initialize the parameter metrics.
|
// Initialize the parameter metrics.
|
||||||
initHotParamMetricsFor(resourceWrapper, rule);
|
ParameterMetricStorage.initParamMetricsFor(resourceWrapper, rule);
|
||||||
|
|
||||||
if (!ParamFlowChecker.passCheck(resourceWrapper, rule, count, args)) {
|
if (!ParamFlowChecker.passCheck(resourceWrapper, rule, count, args)) {
|
||||||
String triggeredParam = "";
|
String triggeredParam = "";
|
||||||
|
|
@ -99,60 +86,4 @@ public class ParamFlowSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<ResourceWrapper, ParameterMetric> getMetricsMap() {
|
|
||||||
return metricsMap;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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<String, ParameterMetric> 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<String, ParameterMetric> getMetricsMap() {
|
||||||
|
return metricsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ParameterMetricStorage() {}
|
||||||
|
}
|
||||||
|
|
@ -20,8 +20,8 @@ import com.alibaba.csp.sentinel.node.DefaultNode;
|
||||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotEntryCallback;
|
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotEntryCallback;
|
||||||
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
|
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
|
||||||
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
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.ParameterMetric;
|
||||||
|
import com.alibaba.csp.sentinel.slots.block.flow.param.ParameterMetricStorage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Eric Zhao
|
* @author Eric Zhao
|
||||||
|
|
@ -32,7 +32,7 @@ public class ParamFlowStatisticEntryCallback implements ProcessorSlotEntryCallba
|
||||||
@Override
|
@Override
|
||||||
public void onPass(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, Object... args) {
|
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.
|
// 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) {
|
if (parameterMetric != null) {
|
||||||
parameterMetric.addThreadCount(args);
|
parameterMetric.addThreadCount(args);
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ package com.alibaba.csp.sentinel.slots.statistic;
|
||||||
import com.alibaba.csp.sentinel.context.Context;
|
import com.alibaba.csp.sentinel.context.Context;
|
||||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotExitCallback;
|
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotExitCallback;
|
||||||
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
|
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.ParameterMetric;
|
||||||
|
import com.alibaba.csp.sentinel.slots.block.flow.param.ParameterMetricStorage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Eric Zhao
|
* @author Eric Zhao
|
||||||
|
|
@ -30,7 +30,7 @@ public class ParamFlowStatisticExitCallback implements ProcessorSlotExitCallback
|
||||||
@Override
|
@Override
|
||||||
public void onExit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
|
public void onExit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
|
||||||
if (context.getCurEntry().getError() == null) {
|
if (context.getCurEntry().getError() == null) {
|
||||||
ParameterMetric parameterMetric = ParamFlowSlot.getParamMetric(resourceWrapper);
|
ParameterMetric parameterMetric = ParameterMetricStorage.getParamMetric(resourceWrapper);
|
||||||
|
|
||||||
if (parameterMetric != null) {
|
if (parameterMetric != null) {
|
||||||
parameterMetric.decreaseThreadCount(args);
|
parameterMetric.decreaseThreadCount(args);
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ public class ParamFlowCheckerTest {
|
||||||
rule.setParsedHotItems(map);
|
rule.setParsedHotItems(map);
|
||||||
|
|
||||||
ParameterMetric metric = new ParameterMetric();
|
ParameterMetric metric = new ParameterMetric();
|
||||||
ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric);
|
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
|
||||||
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
||||||
|
|
||||||
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
|
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, valueB)).thenReturn(globalThreshold - 1);
|
||||||
when(metric.getThreadCount(paramIdx, valueC)).thenReturn(globalThreshold - 1);
|
when(metric.getThreadCount(paramIdx, valueC)).thenReturn(globalThreshold - 1);
|
||||||
when(metric.getThreadCount(paramIdx, valueD)).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));
|
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
|
||||||
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueB));
|
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueB));
|
||||||
|
|
@ -158,7 +158,7 @@ public class ParamFlowCheckerTest {
|
||||||
String v1 = "a", v2 = "B", v3 = "Cc";
|
String v1 = "a", v2 = "B", v3 = "Cc";
|
||||||
List<String> list = Arrays.asList(v1, v2, v3);
|
List<String> list = Arrays.asList(v1, v2, v3);
|
||||||
ParameterMetric metric = new ParameterMetric();
|
ParameterMetric metric = new ParameterMetric();
|
||||||
ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric);
|
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
|
||||||
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
||||||
metric.getRuleTokenCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicInteger>(4000));
|
metric.getRuleTokenCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicInteger>(4000));
|
||||||
|
|
||||||
|
|
@ -181,7 +181,7 @@ public class ParamFlowCheckerTest {
|
||||||
String v1 = "a", v2 = "B", v3 = "Cc";
|
String v1 = "a", v2 = "B", v3 = "Cc";
|
||||||
Object arr = new String[] {v1, v2, v3};
|
Object arr = new String[] {v1, v2, v3};
|
||||||
ParameterMetric metric = new ParameterMetric();
|
ParameterMetric metric = new ParameterMetric();
|
||||||
ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric);
|
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
|
||||||
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
||||||
|
|
||||||
assertTrue(ParamFlowChecker.passCheck(resourceWrapper, rule, 1, arr));
|
assertTrue(ParamFlowChecker.passCheck(resourceWrapper, rule, 1, arr));
|
||||||
|
|
@ -190,11 +190,11 @@ public class ParamFlowCheckerTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
ParamFlowSlot.getMetricsMap().clear();
|
ParameterMetricStorage.getMetricsMap().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
ParamFlowSlot.getMetricsMap().clear();
|
ParameterMetricStorage.getMetricsMap().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
package com.alibaba.csp.sentinel.slots.block.flow.param;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
@ -41,7 +56,7 @@ public class ParamFlowDefaultCheckerTest extends AbstractTimeBasedTest {
|
||||||
|
|
||||||
String valueA = "valueA";
|
String valueA = "valueA";
|
||||||
ParameterMetric metric = new ParameterMetric();
|
ParameterMetric metric = new ParameterMetric();
|
||||||
ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric);
|
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
|
||||||
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
||||||
metric.getRuleTokenCounterMap().put(rule,
|
metric.getRuleTokenCounterMap().put(rule,
|
||||||
new ConcurrentLinkedHashMapWrapper<Object, AtomicInteger>(4000));
|
new ConcurrentLinkedHashMapWrapper<Object, AtomicInteger>(4000));
|
||||||
|
|
@ -81,7 +96,7 @@ public class ParamFlowDefaultCheckerTest extends AbstractTimeBasedTest {
|
||||||
|
|
||||||
String valueA = "valueA";
|
String valueA = "valueA";
|
||||||
ParameterMetric metric = new ParameterMetric();
|
ParameterMetric metric = new ParameterMetric();
|
||||||
ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric);
|
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
|
||||||
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
||||||
metric.getRuleTokenCounterMap().put(rule,
|
metric.getRuleTokenCounterMap().put(rule,
|
||||||
new ConcurrentLinkedHashMapWrapper<Object, AtomicInteger>(4000));
|
new ConcurrentLinkedHashMapWrapper<Object, AtomicInteger>(4000));
|
||||||
|
|
@ -151,7 +166,7 @@ public class ParamFlowDefaultCheckerTest extends AbstractTimeBasedTest {
|
||||||
|
|
||||||
String valueA = "helloWorld";
|
String valueA = "helloWorld";
|
||||||
ParameterMetric metric = new ParameterMetric();
|
ParameterMetric metric = new ParameterMetric();
|
||||||
ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric);
|
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
|
||||||
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
||||||
metric.getRuleTokenCounterMap().put(rule,
|
metric.getRuleTokenCounterMap().put(rule,
|
||||||
new ConcurrentLinkedHashMapWrapper<Object, AtomicInteger>(4000));
|
new ConcurrentLinkedHashMapWrapper<Object, AtomicInteger>(4000));
|
||||||
|
|
@ -204,7 +219,7 @@ public class ParamFlowDefaultCheckerTest extends AbstractTimeBasedTest {
|
||||||
|
|
||||||
final String valueA = "valueA";
|
final String valueA = "valueA";
|
||||||
ParameterMetric metric = new ParameterMetric();
|
ParameterMetric metric = new ParameterMetric();
|
||||||
ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric);
|
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
|
||||||
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
||||||
metric.getRuleTokenCounterMap().put(rule,
|
metric.getRuleTokenCounterMap().put(rule,
|
||||||
new ConcurrentLinkedHashMapWrapper<Object, AtomicInteger>(4000));
|
new ConcurrentLinkedHashMapWrapper<Object, AtomicInteger>(4000));
|
||||||
|
|
@ -270,11 +285,11 @@ public class ParamFlowDefaultCheckerTest extends AbstractTimeBasedTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
ParamFlowSlot.getMetricsMap().clear();
|
ParameterMetricStorage.getMetricsMap().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
ParamFlowSlot.getMetricsMap().clear();
|
ParameterMetricStorage.getMetricsMap().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
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 com.alibaba.csp.sentinel.slots.block.RuleConstant;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
|
@ -40,33 +38,36 @@ public class ParamFlowRuleManagerTest {
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
ParamFlowRuleManager.loadRules(null);
|
ParamFlowRuleManager.loadRules(null);
|
||||||
|
ParameterMetricStorage.getMetricsMap().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
ParamFlowRuleManager.loadRules(null);
|
ParamFlowRuleManager.loadRules(null);
|
||||||
|
ParameterMetricStorage.getMetricsMap().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadHotParamRulesClearingUnusedMetrics() {
|
public void testLoadParamRulesClearingUnusedMetrics() {
|
||||||
final String resA = "resA";
|
final String resA = "resA";
|
||||||
ParamFlowRule ruleA = new ParamFlowRule(resA)
|
ParamFlowRule ruleA = new ParamFlowRule(resA)
|
||||||
.setCount(1)
|
.setCount(1)
|
||||||
.setParamIdx(0);
|
.setParamIdx(0);
|
||||||
ParamFlowRuleManager.loadRules(Collections.singletonList(ruleA));
|
ParamFlowRuleManager.loadRules(Collections.singletonList(ruleA));
|
||||||
ParamFlowSlot.getMetricsMap().put(new StringResourceWrapper(resA, EntryType.IN), new ParameterMetric());
|
ParameterMetricStorage.getMetricsMap().put(resA, new ParameterMetric());
|
||||||
assertNotNull(ParamFlowSlot.getHotParamMetricForName(resA));
|
assertNotNull(ParameterMetricStorage.getParamMetricForResource(resA));
|
||||||
|
|
||||||
final String resB = "resB";
|
final String resB = "resB";
|
||||||
ParamFlowRule ruleB = new ParamFlowRule(resB)
|
ParamFlowRule ruleB = new ParamFlowRule(resB)
|
||||||
.setCount(2)
|
.setCount(2)
|
||||||
.setParamIdx(1);
|
.setParamIdx(1);
|
||||||
ParamFlowRuleManager.loadRules(Collections.singletonList(ruleB));
|
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
|
@Test
|
||||||
public void testLoadHotParamRulesAndGet() {
|
public void testLoadParamRulesAndGet() {
|
||||||
final String resA = "abc";
|
final String resA = "abc";
|
||||||
final String resB = "foo";
|
final String resB = "foo";
|
||||||
final String resC = "baz";
|
final String resC = "baz";
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ public class ParamFlowSlotTest {
|
||||||
ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
|
ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
|
||||||
paramFlowSlot.entry(null, resourceWrapper, null, 1, false, "abc");
|
paramFlowSlot.entry(null, resourceWrapper, null, 1, false, "abc");
|
||||||
// The parameter metric instance will not be created.
|
// The parameter metric instance will not be created.
|
||||||
assertNull(ParamFlowSlot.getParamMetric(resourceWrapper));
|
assertNull(ParameterMetricStorage.getParamMetric(resourceWrapper));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -106,7 +106,7 @@ public class ParamFlowSlotTest {
|
||||||
map.put(argToGo, new AtomicLong(TimeUtil.currentTimeMillis()));
|
map.put(argToGo, new AtomicLong(TimeUtil.currentTimeMillis()));
|
||||||
|
|
||||||
// Insert the mock metric to control pass or block.
|
// 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.
|
// The first entry will pass.
|
||||||
paramFlowSlot.entry(null, resourceWrapper, null, 1, false, argToGo);
|
paramFlowSlot.entry(null, resourceWrapper, null, 1, false, argToGo);
|
||||||
|
|
@ -121,48 +121,16 @@ public class ParamFlowSlotTest {
|
||||||
fail("The second entry should be blocked");
|
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
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() {
|
||||||
ParamFlowRuleManager.loadRules(null);
|
ParamFlowRuleManager.loadRules(null);
|
||||||
ParamFlowSlot.getMetricsMap().clear();
|
ParameterMetricStorage.getMetricsMap().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() {
|
||||||
// Clean the metrics map.
|
// Clean the metrics map.
|
||||||
ParamFlowSlot.getMetricsMap().clear();
|
|
||||||
ParamFlowRuleManager.loadRules(null);
|
ParamFlowRuleManager.loadRules(null);
|
||||||
|
ParameterMetricStorage.getMetricsMap().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
package com.alibaba.csp.sentinel.slots.block.flow.param;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
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.slots.statistic.cache.ConcurrentLinkedHashMapWrapper;
|
||||||
import com.alibaba.csp.sentinel.util.TimeUtil;
|
import com.alibaba.csp.sentinel.util.TimeUtil;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jialiang.linjl
|
* @author jialiang.linjl
|
||||||
*/
|
*/
|
||||||
|
|
@ -41,7 +56,7 @@ public class ParamFlowThrottleRateLimitingCheckerTest {
|
||||||
|
|
||||||
String valueA = "valueA";
|
String valueA = "valueA";
|
||||||
ParameterMetric metric = new ParameterMetric();
|
ParameterMetric metric = new ParameterMetric();
|
||||||
ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric);
|
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
|
||||||
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
||||||
|
|
||||||
long currentTime = TimeUtil.currentTimeMillis();
|
long currentTime = TimeUtil.currentTimeMillis();
|
||||||
|
|
@ -85,7 +100,7 @@ public class ParamFlowThrottleRateLimitingCheckerTest {
|
||||||
|
|
||||||
final String valueA = "valueA";
|
final String valueA = "valueA";
|
||||||
ParameterMetric metric = new ParameterMetric();
|
ParameterMetric metric = new ParameterMetric();
|
||||||
ParamFlowSlot.getMetricsMap().put(resourceWrapper, metric);
|
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
|
||||||
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
|
||||||
|
|
||||||
int threadCount = 40;
|
int threadCount = 40;
|
||||||
|
|
@ -154,11 +169,11 @@ public class ParamFlowThrottleRateLimitingCheckerTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
ParamFlowSlot.getMetricsMap().clear();
|
ParameterMetricStorage.getMetricsMap().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
ParamFlowSlot.getMetricsMap().clear();
|
ParameterMetricStorage.getMetricsMap().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue