use of com.alibaba.csp.sentinel.cluster.flow.statistic.metric.ClusterMetric in project Sentinel by alibaba.
the class ClusterMetricNodeGenerator method flowToMetricNode.
public static ClusterMetricNode flowToMetricNode(long flowId) {
FlowRule rule = ClusterFlowRuleManager.getFlowRuleById(flowId);
if (rule == null) {
return null;
}
ClusterMetric metric = ClusterMetricStatistics.getMetric(flowId);
if (metric == null) {
return new ClusterMetricNode().setFlowId(flowId).setResourceName(rule.getResource());
}
return new ClusterMetricNode().setFlowId(flowId).setResourceName(rule.getResource()).setBlockQps(metric.getAvg(ClusterFlowEvent.BLOCK)).setPassQps(metric.getAvg(ClusterFlowEvent.PASS)).setTimestamp(TimeUtil.currentTimeMillis());
}
use of com.alibaba.csp.sentinel.cluster.flow.statistic.metric.ClusterMetric in project Sentinel by alibaba.
the class SimpleClusterFlowChecker method acquireClusterToken.
public static TokenResult acquireClusterToken(/*@Valid*/
FlowRule rule, int acquireCount) {
Long id = rule.getClusterConfig().getFlowId();
ClusterMetric metric = ClusterMetricStatistics.getMetric(id);
if (metric == null) {
return new TokenResult(TokenResultStatus.FAIL);
}
double latestQps = metric.getAvg(ClusterFlowEvent.PASS);
double globalThreshold = rule.getCount() * ClusterServerConfigManager.getExceedCount();
double nextRemaining = globalThreshold - latestQps - acquireCount;
if (nextRemaining >= 0) {
metric.add(ClusterFlowEvent.PASS, acquireCount);
metric.add(ClusterFlowEvent.PASS_REQUEST, 1);
ClusterServerStatLogUtil.log("flow|pass|" + id, acquireCount);
ClusterServerStatLogUtil.log("flow|pass_request|" + id, 1);
// Remaining count is cut down to a smaller integer.
return new TokenResult(TokenResultStatus.OK).setRemaining((int) nextRemaining).setWaitInMs(0);
} else {
// Blocked.
metric.add(ClusterFlowEvent.BLOCK, acquireCount);
metric.add(ClusterFlowEvent.BLOCK_REQUEST, 1);
ClusterServerStatLogUtil.log("flow|block|" + id, acquireCount);
ClusterServerStatLogUtil.log("flow|block_request|" + id, 1);
return blockedResult();
}
}
use of com.alibaba.csp.sentinel.cluster.flow.statistic.metric.ClusterMetric in project Sentinel by alibaba.
the class ClusterFlowCheckerTest method testAcquireClusterTokenOccupyPass.
// @Test
public void testAcquireClusterTokenOccupyPass() {
long flowId = 98765L;
final int threshold = 5;
FlowRule clusterRule = new FlowRule("abc").setCount(threshold).setClusterMode(true).setClusterConfig(new ClusterFlowConfig().setFlowId(flowId).setThresholdType(ClusterRuleConstant.FLOW_THRESHOLD_GLOBAL));
int sampleCount = 5;
int intervalInMs = 1000;
int bucketLength = intervalInMs / sampleCount;
ClusterMetric metric = new ClusterMetric(sampleCount, intervalInMs);
ClusterMetricStatistics.putMetric(flowId, metric);
System.out.println(System.currentTimeMillis());
assertResultPass(tryAcquire(clusterRule, false));
assertResultPass(tryAcquire(clusterRule, false));
sleep(bucketLength);
assertResultPass(tryAcquire(clusterRule, false));
sleep(bucketLength);
assertResultPass(tryAcquire(clusterRule, true));
assertResultPass(tryAcquire(clusterRule, false));
assertResultBlock(tryAcquire(clusterRule, true));
sleep(bucketLength);
assertResultBlock(tryAcquire(clusterRule, false));
assertResultBlock(tryAcquire(clusterRule, false));
sleep(bucketLength);
assertResultBlock(tryAcquire(clusterRule, false));
assertResultWait(tryAcquire(clusterRule, true), bucketLength);
assertResultBlock(tryAcquire(clusterRule, false));
sleep(bucketLength);
assertResultPass(tryAcquire(clusterRule, false));
ClusterMetricStatistics.removeMetric(flowId);
}
use of com.alibaba.csp.sentinel.cluster.flow.statistic.metric.ClusterMetric in project Sentinel by alibaba.
the class ClusterFlowChecker method acquireClusterToken.
static TokenResult acquireClusterToken(/*@Valid*/
FlowRule rule, int acquireCount, boolean prioritized) {
Long id = rule.getClusterConfig().getFlowId();
if (!allowProceed(id)) {
return new TokenResult(TokenResultStatus.TOO_MANY_REQUEST);
}
ClusterMetric metric = ClusterMetricStatistics.getMetric(id);
if (metric == null) {
return new TokenResult(TokenResultStatus.FAIL);
}
double latestQps = metric.getAvg(ClusterFlowEvent.PASS);
double globalThreshold = calcGlobalThreshold(rule) * ClusterServerConfigManager.getExceedCount();
double nextRemaining = globalThreshold - latestQps - acquireCount;
if (nextRemaining >= 0) {
// TODO: checking logic and metric operation should be separated.
metric.add(ClusterFlowEvent.PASS, acquireCount);
metric.add(ClusterFlowEvent.PASS_REQUEST, 1);
if (prioritized) {
// Add prioritized pass.
metric.add(ClusterFlowEvent.OCCUPIED_PASS, acquireCount);
}
// Remaining count is cut down to a smaller integer.
return new TokenResult(TokenResultStatus.OK).setRemaining((int) nextRemaining).setWaitInMs(0);
} else {
if (prioritized) {
// Try to occupy incoming buckets.
double occupyAvg = metric.getAvg(ClusterFlowEvent.WAITING);
if (occupyAvg <= ClusterServerConfigManager.getMaxOccupyRatio() * globalThreshold) {
int waitInMs = metric.tryOccupyNext(ClusterFlowEvent.PASS, acquireCount, globalThreshold);
// waitInMs > 0 indicates pre-occupy incoming buckets successfully.
if (waitInMs > 0) {
ClusterServerStatLogUtil.log("flow|waiting|" + id);
return new TokenResult(TokenResultStatus.SHOULD_WAIT).setRemaining(0).setWaitInMs(waitInMs);
}
// Or else occupy failed, should be blocked.
}
}
// Blocked.
metric.add(ClusterFlowEvent.BLOCK, acquireCount);
metric.add(ClusterFlowEvent.BLOCK_REQUEST, 1);
ClusterServerStatLogUtil.log("flow|block|" + id, acquireCount);
ClusterServerStatLogUtil.log("flow|block_request|" + id, 1);
if (prioritized) {
// Add prioritized block.
metric.add(ClusterFlowEvent.OCCUPIED_BLOCK, acquireCount);
ClusterServerStatLogUtil.log("flow|occupied_block|" + id, 1);
}
return blockedResult();
}
}
use of com.alibaba.csp.sentinel.cluster.flow.statistic.metric.ClusterMetric in project Sentinel by alibaba.
the class ClusterFlowRuleManager method applyClusterFlowRule.
private static void applyClusterFlowRule(List<FlowRule> list, /*@Valid*/
String namespace) {
if (list == null || list.isEmpty()) {
clearAndResetRulesFor(namespace);
return;
}
final ConcurrentHashMap<Long, FlowRule> ruleMap = new ConcurrentHashMap<>();
Set<Long> flowIdSet = new HashSet<>();
for (FlowRule rule : list) {
if (!rule.isClusterMode()) {
continue;
}
if (!FlowRuleUtil.isValidRule(rule)) {
RecordLog.warn("[ClusterFlowRuleManager] Ignoring invalid flow rule when loading new flow rules: " + rule);
continue;
}
if (StringUtil.isBlank(rule.getLimitApp())) {
rule.setLimitApp(RuleConstant.LIMIT_APP_DEFAULT);
}
// Flow id should not be null after filtered.
ClusterFlowConfig clusterConfig = rule.getClusterConfig();
Long flowId = clusterConfig.getFlowId();
if (flowId == null) {
continue;
}
ruleMap.put(flowId, rule);
FLOW_NAMESPACE_MAP.put(flowId, namespace);
flowIdSet.add(flowId);
if (!CurrentConcurrencyManager.containsFlowId(flowId)) {
CurrentConcurrencyManager.put(flowId, 0);
}
// Prepare cluster metric from valid flow ID.
ClusterMetricStatistics.putMetricIfAbsent(flowId, new ClusterMetric(clusterConfig.getSampleCount(), clusterConfig.getWindowIntervalMs()));
}
// Cleanup unused cluster metrics.
clearAndResetRulesConditional(namespace, new Predicate<Long>() {
@Override
public boolean test(Long flowId) {
return !ruleMap.containsKey(flowId);
}
});
FLOW_RULES.putAll(ruleMap);
NAMESPACE_FLOW_ID_MAP.put(namespace, flowIdSet);
}
Aggregations