Improve deprecated ParameterMetric purge mechanism (#1372)

* Clear useless data in ParameterMetric for all removed rules
This commit is contained in:
wavesZh 2020-05-07 20:04:12 +08:00 committed by GitHub
parent d84d681dd8
commit 096a9ebf7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 15 deletions

View File

@ -217,10 +217,17 @@ public final class GatewayRuleManager {
} }
// Clear unused parameter metrics. // Clear unused parameter metrics.
Set<String> previousResources = CONVERTED_PARAM_RULE_MAP.keySet(); for (Map.Entry<String, List<ParamFlowRule>> entry : CONVERTED_PARAM_RULE_MAP.entrySet()) {
for (String resource : previousResources) { String resource = entry.getKey();
if (!newRuleMap.containsKey(resource)) { if (!newRuleMap.containsKey(resource)) {
ParameterMetricStorage.clearParamMetricForResource(resource); ParameterMetricStorage.clearParamMetricForResource(resource);
continue;
}
List<ParamFlowRule> newRuleList = newRuleMap.get(resource);
List<ParamFlowRule> oldRuleList = new ArrayList<>(entry.getValue());
oldRuleList.removeAll(newRuleList);
for (ParamFlowRule rule : oldRuleList) {
ParameterMetricStorage.getParamMetricForResource(resource).clearForRule(rule);
} }
} }

View File

@ -18,7 +18,6 @@ package com.alibaba.csp.sentinel.slots.block.flow.param;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.csp.sentinel.log.RecordLog; import com.alibaba.csp.sentinel.log.RecordLog;
@ -36,7 +35,7 @@ import com.alibaba.csp.sentinel.util.AssertUtil;
*/ */
public final class ParamFlowRuleManager { public final class ParamFlowRuleManager {
private static final Map<String, List<ParamFlowRule>> paramFlowRules = new ConcurrentHashMap<>(); private static final Map<String, List<ParamFlowRule>> PARAM_FLOW_RULES = 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<>();
@ -76,11 +75,11 @@ public final class ParamFlowRuleManager {
} }
public static List<ParamFlowRule> getRulesOfResource(String resourceName) { public static List<ParamFlowRule> getRulesOfResource(String resourceName) {
return new ArrayList<>(paramFlowRules.get(resourceName)); return new ArrayList<>(PARAM_FLOW_RULES.get(resourceName));
} }
public static boolean hasRules(String resourceName) { public static boolean hasRules(String resourceName) {
List<ParamFlowRule> rules = paramFlowRules.get(resourceName); List<ParamFlowRule> rules = PARAM_FLOW_RULES.get(resourceName);
return rules != null && !rules.isEmpty(); return rules != null && !rules.isEmpty();
} }
@ -91,7 +90,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, List<ParamFlowRule>> entry : paramFlowRules.entrySet()) { for (Map.Entry<String, List<ParamFlowRule>> entry : PARAM_FLOW_RULES.entrySet()) {
rules.addAll(entry.getValue()); rules.addAll(entry.getValue());
} }
return rules; return rules;
@ -103,20 +102,20 @@ public final class ParamFlowRuleManager {
public void configUpdate(List<ParamFlowRule> list) { public void configUpdate(List<ParamFlowRule> list) {
Map<String, List<ParamFlowRule>> rules = aggregateAndPrepareParamRules(list); Map<String, List<ParamFlowRule>> rules = aggregateAndPrepareParamRules(list);
if (rules != null) { if (rules != null) {
paramFlowRules.clear(); PARAM_FLOW_RULES.clear();
paramFlowRules.putAll(rules); PARAM_FLOW_RULES.putAll(rules);
} }
RecordLog.info("[ParamFlowRuleManager] Parameter flow rules received: " + paramFlowRules); RecordLog.info("[ParamFlowRuleManager] Parameter flow rules received: " + PARAM_FLOW_RULES);
} }
@Override @Override
public void configLoad(List<ParamFlowRule> list) { public void configLoad(List<ParamFlowRule> list) {
Map<String, List<ParamFlowRule>> rules = aggregateAndPrepareParamRules(list); Map<String, List<ParamFlowRule>> rules = aggregateAndPrepareParamRules(list);
if (rules != null) { if (rules != null) {
paramFlowRules.clear(); PARAM_FLOW_RULES.clear();
paramFlowRules.putAll(rules); PARAM_FLOW_RULES.putAll(rules);
} }
RecordLog.info("[ParamFlowRuleManager] Parameter flow rules received: " + paramFlowRules); RecordLog.info("[ParamFlowRuleManager] Parameter flow rules received: " + PARAM_FLOW_RULES);
} }
private Map<String, List<ParamFlowRule>> aggregateAndPrepareParamRules(List<ParamFlowRule> list) { private Map<String, List<ParamFlowRule>> aggregateAndPrepareParamRules(List<ParamFlowRule> list) {
@ -129,10 +128,17 @@ public final class ParamFlowRuleManager {
} }
// Clear unused parameter metrics. // Clear unused parameter metrics.
Set<String> previousResources = paramFlowRules.keySet(); for (Map.Entry<String, List<ParamFlowRule>> entry : PARAM_FLOW_RULES.entrySet()) {
for (String resource : previousResources) { String resource = entry.getKey();
if (!newRuleMap.containsKey(resource)) { if (!newRuleMap.containsKey(resource)) {
ParameterMetricStorage.clearParamMetricForResource(resource); ParameterMetricStorage.clearParamMetricForResource(resource);
continue;
}
List<ParamFlowRule> newRuleList = newRuleMap.get(resource);
List<ParamFlowRule> oldRuleList = new ArrayList<>(entry.getValue());
oldRuleList.removeAll(newRuleList);
for (ParamFlowRule rule : oldRuleList) {
ParameterMetricStorage.getParamMetricForResource(resource).clearForRule(rule);
} }
} }

View File

@ -84,6 +84,14 @@ public class ParameterMetric {
} }
} }
public void clearForRule(ParamFlowRule rule) {
synchronized (lock) {
ruleTimeCounters.remove(rule);
ruleTokenCounter.remove(rule);
threadCountMap.remove(rule.getParamIdx());
}
}
public void initialize(ParamFlowRule rule) { public void initialize(ParamFlowRule rule) {
if (!ruleTimeCounters.containsKey(rule)) { if (!ruleTimeCounters.containsKey(rule)) {
synchronized (lock) { synchronized (lock) {

View File

@ -66,6 +66,36 @@ public class ParamFlowRuleManagerTest {
ParameterMetricStorage.getParamMetricForResource(resA)); ParameterMetricStorage.getParamMetricForResource(resA));
} }
@Test
public void testLoadParamRulesClearingUnusedMetricsForRule() {
final String resA = "resA";
ParamFlowRule ruleA1 = new ParamFlowRule(resA)
.setCount(1)
.setParamIdx(0);
ParamFlowRule ruleA2 = new ParamFlowRule(resA)
.setCount(2)
.setParamIdx(1);
ParamFlowRuleManager.loadRules(Arrays.asList(ruleA1, ruleA2));
ParameterMetric metric = new ParameterMetric();
metric.initialize(ruleA1);
metric.initialize(ruleA2);
ParameterMetricStorage.getMetricsMap().put(resA, metric);
ParameterMetric metric1 = ParameterMetricStorage.getParamMetricForResource(resA);
assertNotNull(metric1);
assertNotNull(metric1.getRuleTimeCounter(ruleA1));
assertNotNull(metric1.getRuleTimeCounter(ruleA2));
ParamFlowRuleManager.loadRules(Arrays.asList(ruleA1));
ParameterMetric metric2 = ParameterMetricStorage.getParamMetricForResource(resA);
assertNotNull(metric2);
assertNotNull(metric2.getRuleTimeCounter(ruleA1));
assertNull(metric2.getRuleTimeCounter(ruleA2));
}
@Test @Test
public void testLoadParamRulesAndGet() { public void testLoadParamRulesAndGet() {
final String resA = "abc"; final String resA = "abc";