Signed-off-by: Eric Zhao <sczyh16@gmail.com>master
@@ -27,5 +27,7 @@ public final class ClusterRuleConstant { | |||
public static final int FLOW_THRESHOLD_AVG_LOCAL = 0; | |||
public static final int FLOW_THRESHOLD_GLOBAL = 1; | |||
public static final int DEFAULT_CLUSTER_SAMPLE_COUNT = 10; | |||
private ClusterRuleConstant() {} | |||
} |
@@ -16,6 +16,7 @@ | |||
package com.alibaba.csp.sentinel.slots.block.flow; | |||
import com.alibaba.csp.sentinel.slots.block.ClusterRuleConstant; | |||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |||
/** | |||
* Flow rule config in cluster mode. | |||
@@ -41,6 +42,12 @@ public class ClusterFlowConfig { | |||
*/ | |||
private int strategy = ClusterRuleConstant.FLOW_CLUSTER_STRATEGY_NORMAL; | |||
private int sampleCount = ClusterRuleConstant.DEFAULT_CLUSTER_SAMPLE_COUNT; | |||
/** | |||
* The time interval length of the statistic sliding window (in milliseconds) | |||
*/ | |||
private int windowIntervalMs = RuleConstant.DEFAULT_WINDOW_INTERVAL_MS; | |||
public Long getFlowId() { | |||
return flowId; | |||
} | |||
@@ -77,6 +84,24 @@ public class ClusterFlowConfig { | |||
return this; | |||
} | |||
public int getSampleCount() { | |||
return sampleCount; | |||
} | |||
public ClusterFlowConfig setSampleCount(int sampleCount) { | |||
this.sampleCount = sampleCount; | |||
return this; | |||
} | |||
public int getWindowIntervalMs() { | |||
return windowIntervalMs; | |||
} | |||
public ClusterFlowConfig setWindowIntervalMs(int windowIntervalMs) { | |||
this.windowIntervalMs = windowIntervalMs; | |||
return this; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { return true; } | |||
@@ -87,6 +112,8 @@ public class ClusterFlowConfig { | |||
if (thresholdType != that.thresholdType) { return false; } | |||
if (fallbackToLocalWhenFail != that.fallbackToLocalWhenFail) { return false; } | |||
if (strategy != that.strategy) { return false; } | |||
if (sampleCount != that.sampleCount) { return false; } | |||
if (windowIntervalMs != that.windowIntervalMs) { return false; } | |||
return flowId != null ? flowId.equals(that.flowId) : that.flowId == null; | |||
} | |||
@@ -96,6 +123,8 @@ public class ClusterFlowConfig { | |||
result = 31 * result + thresholdType; | |||
result = 31 * result + (fallbackToLocalWhenFail ? 1 : 0); | |||
result = 31 * result + strategy; | |||
result = 31 * result + sampleCount; | |||
result = 31 * result + windowIntervalMs; | |||
return result; | |||
} | |||
@@ -106,6 +135,8 @@ public class ClusterFlowConfig { | |||
", thresholdType=" + thresholdType + | |||
", fallbackToLocalWhenFail=" + fallbackToLocalWhenFail + | |||
", strategy=" + strategy + | |||
", sampleCount=" + sampleCount + | |||
", windowIntervalMs=" + windowIntervalMs + | |||
'}'; | |||
} | |||
} |
@@ -186,6 +186,9 @@ public final class FlowRuleUtil { | |||
if (!validClusterRuleId(clusterConfig.getFlowId())) { | |||
return false; | |||
} | |||
if (!isWindowConfigValid(clusterConfig.getSampleCount(), clusterConfig.getWindowIntervalMs())) { | |||
return false; | |||
} | |||
switch (rule.getStrategy()) { | |||
case ClusterRuleConstant.FLOW_CLUSTER_STRATEGY_NORMAL: | |||
return true; | |||
@@ -194,6 +197,10 @@ public final class FlowRuleUtil { | |||
} | |||
} | |||
public static boolean isWindowConfigValid(int sampleCount, int windowIntervalMs) { | |||
return sampleCount > 0 && windowIntervalMs > 0 && windowIntervalMs % sampleCount == 0; | |||
} | |||
private static boolean checkStrategyField(/*@NonNull*/ FlowRule rule) { | |||
if (rule.getStrategy() == RuleConstant.STRATEGY_RELATE || rule.getStrategy() == RuleConstant.STRATEGY_CHAIN) { | |||
return StringUtil.isNotBlank(rule.getRefResource()); | |||
@@ -16,6 +16,7 @@ | |||
package com.alibaba.csp.sentinel.slots.block.flow.param; | |||
import com.alibaba.csp.sentinel.slots.block.ClusterRuleConstant; | |||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |||
/** | |||
* Parameter flow rule config in cluster mode. | |||
@@ -36,6 +37,12 @@ public class ParamFlowClusterConfig { | |||
private int thresholdType = ClusterRuleConstant.FLOW_THRESHOLD_AVG_LOCAL; | |||
private boolean fallbackToLocalWhenFail = false; | |||
private int sampleCount = ClusterRuleConstant.DEFAULT_CLUSTER_SAMPLE_COUNT; | |||
/** | |||
* The time interval length of the statistic sliding window (in milliseconds) | |||
*/ | |||
private int windowIntervalMs = RuleConstant.DEFAULT_WINDOW_INTERVAL_MS; | |||
public Long getFlowId() { | |||
return flowId; | |||
} | |||
@@ -63,16 +70,36 @@ public class ParamFlowClusterConfig { | |||
return this; | |||
} | |||
public int getSampleCount() { | |||
return sampleCount; | |||
} | |||
public ParamFlowClusterConfig setSampleCount(int sampleCount) { | |||
this.sampleCount = sampleCount; | |||
return this; | |||
} | |||
public int getWindowIntervalMs() { | |||
return windowIntervalMs; | |||
} | |||
public ParamFlowClusterConfig setWindowIntervalMs(int windowIntervalMs) { | |||
this.windowIntervalMs = windowIntervalMs; | |||
return this; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { return true; } | |||
if (o == null || getClass() != o.getClass()) { return false; } | |||
ParamFlowClusterConfig that = (ParamFlowClusterConfig)o; | |||
ParamFlowClusterConfig config = (ParamFlowClusterConfig)o; | |||
if (thresholdType != that.thresholdType) { return false; } | |||
if (fallbackToLocalWhenFail != that.fallbackToLocalWhenFail) { return false; } | |||
return flowId != null ? flowId.equals(that.flowId) : that.flowId == null; | |||
if (thresholdType != config.thresholdType) { return false; } | |||
if (fallbackToLocalWhenFail != config.fallbackToLocalWhenFail) { return false; } | |||
if (sampleCount != config.sampleCount) { return false; } | |||
if (windowIntervalMs != config.windowIntervalMs) { return false; } | |||
return flowId != null ? flowId.equals(config.flowId) : config.flowId == null; | |||
} | |||
@Override | |||
@@ -80,6 +107,8 @@ public class ParamFlowClusterConfig { | |||
int result = flowId != null ? flowId.hashCode() : 0; | |||
result = 31 * result + thresholdType; | |||
result = 31 * result + (fallbackToLocalWhenFail ? 1 : 0); | |||
result = 31 * result + sampleCount; | |||
result = 31 * result + windowIntervalMs; | |||
return result; | |||
} | |||
@@ -89,6 +118,8 @@ public class ParamFlowClusterConfig { | |||
"flowId=" + flowId + | |||
", thresholdType=" + thresholdType + | |||
", fallbackToLocalWhenFail=" + fallbackToLocalWhenFail + | |||
", sampleCount=" + sampleCount + | |||
", windowIntervalMs=" + windowIntervalMs + | |||
'}'; | |||
} | |||
} |
@@ -65,7 +65,13 @@ public class ParamFlowRule extends AbstractRule { | |||
*/ | |||
private Map<Object, Integer> hotItems = new HashMap<Object, Integer>(); | |||
/** | |||
* Indicating whether the rule is for cluster mode. | |||
*/ | |||
private boolean clusterMode = false; | |||
/** | |||
* Cluster mode specific config for parameter flow rule. | |||
*/ | |||
private ParamFlowClusterConfig clusterConfig; | |||
public int getGrade() { | |||
@@ -21,6 +21,7 @@ import java.util.List; | |||
import java.util.Map; | |||
import com.alibaba.csp.sentinel.log.RecordLog; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleUtil; | |||
import com.alibaba.csp.sentinel.util.StringUtil; | |||
/** | |||
@@ -38,7 +39,13 @@ public final class ParamFlowRuleUtil { | |||
return true; | |||
} | |||
ParamFlowClusterConfig clusterConfig = rule.getClusterConfig(); | |||
return clusterConfig != null && validClusterRuleId(clusterConfig.getFlowId()); | |||
if (clusterConfig == null) { | |||
return false; | |||
} | |||
if (!FlowRuleUtil.isWindowConfigValid(clusterConfig.getSampleCount(), clusterConfig.getWindowIntervalMs())) { | |||
return false; | |||
} | |||
return validClusterRuleId(clusterConfig.getFlowId()); | |||
} | |||
public static boolean validClusterRuleId(Long id) { | |||