Skip to content

Commit

Permalink
Polish default cluster server module for initial work
Browse files Browse the repository at this point in the history
Signed-off-by: Eric Zhao <[email protected]>
  • Loading branch information
sczyh30 committed Dec 14, 2018
1 parent 138c265 commit a731811
Show file tree
Hide file tree
Showing 49 changed files with 2,158 additions and 507 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,111 +17,22 @@

import com.alibaba.csp.sentinel.cluster.TokenResultStatus;
import com.alibaba.csp.sentinel.cluster.TokenResult;
import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterFlowRuleManager;
import com.alibaba.csp.sentinel.cluster.flow.statistic.ClusterMetricStatistics;
import com.alibaba.csp.sentinel.cluster.server.config.ClusterServerConfigManager;
import com.alibaba.csp.sentinel.cluster.flow.statistic.data.ClusterFlowEvent;
import com.alibaba.csp.sentinel.cluster.flow.statistic.metric.ClusterMetric;
import com.alibaba.csp.sentinel.cluster.server.log.ClusterServerStatLogUtil;
import com.alibaba.csp.sentinel.slots.block.ClusterRuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.util.TimeUtil;

/**
* Flow checker for cluster flow rules.
*
* @author Eric Zhao
* @since 1.4.0
*/
public final class ClusterFlowChecker {

static TokenResult tryAcquireOrBorrowFromRefResource(FlowRule rule, int acquireCount, boolean prioritized) {
// 1. First try acquire its own count.

// TokenResult ownResult = acquireClusterToken(rule, acquireCount, prioritized);
ClusterMetric metric = ClusterMetricStatistics.getMetric(rule.getClusterConfig().getFlowId());
if (metric == null) {
return new TokenResult(TokenResultStatus.FAIL);
}

double latestQps = metric.getAvg(ClusterFlowEvent.PASS_REQUEST);
double globalThreshold = calcGlobalThreshold(rule) * ClusterServerConfigManager.exceedCount;
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);
}

if (prioritized) {
double occupyAvg = metric.getAvg(ClusterFlowEvent.WAITING);
if (occupyAvg <= ClusterServerConfigManager.maxOccupyRatio * globalThreshold) {
int waitInMs = metric.tryOccupyNext(ClusterFlowEvent.PASS, acquireCount, globalThreshold);
if (waitInMs > 0) {
return new TokenResult(TokenResultStatus.SHOULD_WAIT)
.setRemaining(0)
.setWaitInMs(waitInMs);
}
// Or else occupy failed, should be blocked.
}
}

// 2. If failed, try to borrow from reference resource.

// Assume it's valid as checked before.
if (!ClusterServerConfigManager.borrowRefEnabled) {
return new TokenResult(TokenResultStatus.NOT_AVAILABLE);
}
Long refFlowId = rule.getClusterConfig().getRefFlowId();
FlowRule refFlowRule = ClusterFlowRuleManager.getFlowRuleById(refFlowId);
if (refFlowRule == null) {
return new TokenResult(TokenResultStatus.NO_REF_RULE_EXISTS);
}
// TODO: check here

ClusterMetric refMetric = ClusterMetricStatistics.getMetric(refFlowId);
if (refMetric == null) {
return new TokenResult(TokenResultStatus.FAIL);
}
double refOrders = refMetric.getAvg(ClusterFlowEvent.PASS);
double refQps = refMetric.getAvg(ClusterFlowEvent.PASS_REQUEST);

double splitRatio = refQps > 0 ? refOrders / refQps : 1;

double selfGlobalThreshold = ClusterServerConfigManager.exceedCount * calcGlobalThreshold(rule);
double refGlobalThreshold = ClusterServerConfigManager.exceedCount * calcGlobalThreshold(refFlowRule);

long currentTime = TimeUtil.currentTimeMillis();
long latestRefTime = 0 /*refFlowRule.clusterQps.getStableWindowStartTime()*/;
int sampleCount = 10;

if (currentTime > latestRefTime
&& (refOrders / refGlobalThreshold + 1.0d / sampleCount >= ((double)(currentTime - latestRefTime)) / 1000)
|| refOrders == refGlobalThreshold) {
return blockedResult();
}

// double latestQps = metric.getAvg(ClusterFlowEvent.PASS);
double refRatio = rule.getClusterConfig().getRefRatio();

if (refOrders / splitRatio + (acquireCount + latestQps) * refRatio
<= refGlobalThreshold / splitRatio + selfGlobalThreshold * refRatio) {
metric.add(ClusterFlowEvent.PASS, acquireCount);
metric.add(ClusterFlowEvent.PASS_REQUEST, 1);

return new TokenResult(TokenResultStatus.OK);
}

// TODO: log here?
metric.add(ClusterFlowEvent.BLOCK, acquireCount);

return blockedResult();
}
final class ClusterFlowChecker {

private static double calcGlobalThreshold(FlowRule rule) {
double count = rule.getCount();
Expand All @@ -130,20 +41,20 @@ private static double calcGlobalThreshold(FlowRule rule) {
return count;
case ClusterRuleConstant.FLOW_THRESHOLD_AVG_LOCAL:
default:
// TODO: get real connected count grouped.
int connectedCount = 1;
int connectedCount = ClusterFlowRuleManager.getConnectedCount(rule.getClusterConfig().getFlowId());
return count * connectedCount;
}
}

static TokenResult acquireClusterToken(/*@Valid*/ FlowRule rule, int acquireCount, boolean prioritized) {
ClusterMetric metric = ClusterMetricStatistics.getMetric(rule.getClusterConfig().getFlowId());
Long id = rule.getClusterConfig().getFlowId();
ClusterMetric metric = ClusterMetricStatistics.getMetric(id);
if (metric == null) {
return new TokenResult(TokenResultStatus.FAIL);
}

double latestQps = metric.getAvg(ClusterFlowEvent.PASS_REQUEST);
double globalThreshold = calcGlobalThreshold(rule) * ClusterServerConfigManager.exceedCount;
double globalThreshold = calcGlobalThreshold(rule) * ClusterServerConfigManager.getExceedCount();
double nextRemaining = globalThreshold - latestQps - acquireCount;

if (nextRemaining >= 0) {
Expand All @@ -160,10 +71,13 @@ static TokenResult acquireClusterToken(/*@Valid*/ FlowRule rule, int acquireCoun
.setWaitInMs(0);
} else {
if (prioritized) {
// Try to occupy incoming buckets.
double occupyAvg = metric.getAvg(ClusterFlowEvent.WAITING);
if (occupyAvg <= ClusterServerConfigManager.maxOccupyRatio * globalThreshold) {
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);
Expand All @@ -174,9 +88,12 @@ static TokenResult acquireClusterToken(/*@Valid*/ FlowRule rule, int acquireCoun
// 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();
Expand Down

This file was deleted.

Loading

0 comments on commit a731811

Please sign in to comment.