Refactor Node interface: change return type of `xxxQps` method from long to double (#564)

- Update test cases (use assertEquals(e, a, delta) instead)
- Also add `totalPass` method in Node interface

Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
Eric Zhao 2019-03-13 22:10:20 +08:00 committed by GitHub
parent 63d7c9d207
commit 4b1ccd93e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 200 additions and 127 deletions

View File

@ -45,7 +45,7 @@ public class FluxSentinelOperatorTestIntegrationTest {
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName); ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertNotNull(cn); assertNotNull(cn);
assertEquals(1, cn.passQps()); assertEquals(1, cn.passQps(), 0.01);
assertEquals(1, cn.totalException()); assertEquals(1, cn.totalException());
} }

View File

@ -68,7 +68,7 @@ public class SentinelWebFluxIntegrationTest {
ClusterNode cn = ClusterBuilderSlot.getClusterNode(url); ClusterNode cn = ClusterBuilderSlot.getClusterNode(url);
assertNotNull(cn); assertNotNull(cn);
assertEquals(1, cn.passQps()); assertEquals(1, cn.passQps(), 0.01);
} }
@Test @Test
@ -94,7 +94,7 @@ public class SentinelWebFluxIntegrationTest {
.expectBody(String.class).isEqualTo("Hello 2"); .expectBody(String.class).isEqualTo("Hello 2");
ClusterNode cn = ClusterBuilderSlot.getClusterNode(fooPrefix + "*"); ClusterNode cn = ClusterBuilderSlot.getClusterNode(fooPrefix + "*");
assertEquals(2, cn.passQps()); assertEquals(2, cn.passQps(), 0.01);
assertNull(ClusterBuilderSlot.getClusterNode(url1)); assertNull(ClusterBuilderSlot.getClusterNode(url1));
assertNull(ClusterBuilderSlot.getClusterNode(url2)); assertNull(ClusterBuilderSlot.getClusterNode(url2));

View File

@ -83,7 +83,7 @@ public class CommonFilterTest {
ClusterNode cn = ClusterBuilderSlot.getClusterNode(url); ClusterNode cn = ClusterBuilderSlot.getClusterNode(url);
assertNotNull(cn); assertNotNull(cn);
assertEquals(1, cn.passQps()); assertEquals(1, cn.passQps(), 0.01);
testCommonBlockAndRedirectBlockPage(url, cn); testCommonBlockAndRedirectBlockPage(url, cn);
@ -99,7 +99,7 @@ public class CommonFilterTest {
this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN)) this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().string(FilterUtil.DEFAULT_BLOCK_MSG)); .andExpect(content().string(FilterUtil.DEFAULT_BLOCK_MSG));
assertEquals(1, cn.blockQps()); assertEquals(1, cn.blockQps(), 0.01);
// Test for redirect. // Test for redirect.
String redirectUrl = "http://some-location.com"; String redirectUrl = "http://some-location.com";
@ -132,7 +132,7 @@ public class CommonFilterTest {
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().string("Hello 2")); .andExpect(content().string("Hello 2"));
ClusterNode cn = ClusterBuilderSlot.getClusterNode(fooPrefix + "*"); ClusterNode cn = ClusterBuilderSlot.getClusterNode(fooPrefix + "*");
assertEquals(2, cn.passQps()); assertEquals(2, cn.passQps(), 0.01);
assertNull(ClusterBuilderSlot.getClusterNode(url1)); assertNull(ClusterBuilderSlot.getClusterNode(url1));
assertNull(ClusterBuilderSlot.getClusterNode(url2)); assertNull(ClusterBuilderSlot.getClusterNode(url2));

View File

@ -86,7 +86,7 @@ public class CommonFilterMethodTest {
ClusterNode cnGet = ClusterBuilderSlot.getClusterNode(GET + COLON + url); ClusterNode cnGet = ClusterBuilderSlot.getClusterNode(GET + COLON + url);
assertNotNull(cnGet); assertNotNull(cnGet);
assertEquals(1, cnGet.passQps()); assertEquals(1, cnGet.passQps(), 0.01);
ClusterNode cnPost = ClusterBuilderSlot.getClusterNode(POST + COLON + url); ClusterNode cnPost = ClusterBuilderSlot.getClusterNode(POST + COLON + url);
@ -98,10 +98,9 @@ public class CommonFilterMethodTest {
cnPost = ClusterBuilderSlot.getClusterNode(POST + COLON + url); cnPost = ClusterBuilderSlot.getClusterNode(POST + COLON + url);
assertNotNull(cnPost); assertNotNull(cnPost);
assertEquals(1, cnPost.passQps()); assertEquals(1, cnPost.passQps(), 0.01);
testCommonBlockAndRedirectBlockPage(url, cnGet, cnPost); testCommonBlockAndRedirectBlockPage(url, cnGet, cnPost);
} }
private void testCommonBlockAndRedirectBlockPage(String url, ClusterNode cnGet, ClusterNode cnPost) throws Exception { private void testCommonBlockAndRedirectBlockPage(String url, ClusterNode cnGet, ClusterNode cnPost) throws Exception {
@ -110,21 +109,20 @@ public class CommonFilterMethodTest {
this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN)) this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().string(FilterUtil.DEFAULT_BLOCK_MSG)); .andExpect(content().string(FilterUtil.DEFAULT_BLOCK_MSG));
assertEquals(1, cnGet.blockQps()); assertEquals(1, cnGet.blockQps(), 0.01);
// Test for post pass // Test for post pass
this.mvc.perform(post(url)) this.mvc.perform(post(url))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().string(HELLO_POST_STR)); .andExpect(content().string(HELLO_POST_STR));
assertEquals(2, cnPost.passQps()); assertEquals(2, cnPost.passQps(), 0.01);
FlowRuleManager.loadRules(null); FlowRuleManager.loadRules(null);
WebServletConfig.setBlockPage(""); WebServletConfig.setBlockPage("");
} }
@After @After
public void cleanUp() { public void cleanUp() {
FlowRuleManager.loadRules(null); FlowRuleManager.loadRules(null);

View File

@ -48,7 +48,7 @@ public class DefaultNode extends StatisticNode {
/** /**
* The list of all child nodes. * The list of all child nodes.
*/ */
private volatile Set<Node> childList = new HashSet<Node>(); private volatile Set<Node> childList = new HashSet<>();
/** /**
* Associated cluster node. * Associated cluster node.
@ -85,7 +85,7 @@ public class DefaultNode extends StatisticNode {
if (!childList.contains(node)) { if (!childList.contains(node)) {
synchronized (this) { synchronized (this) {
if (!childList.contains(node)) { if (!childList.contains(node)) {
Set<Node> newSet = new HashSet<Node>(childList.size() + 1); Set<Node> newSet = new HashSet<>(childList.size() + 1);
newSet.addAll(childList); newSet.addAll(childList);
newSet.add(node); newSet.add(node);
childList = newSet; childList = newSet;
@ -99,7 +99,7 @@ public class DefaultNode extends StatisticNode {
* Reset the child node list. * Reset the child node list.
*/ */
public void removeChildList() { public void removeChildList() {
this.childList = new HashSet<Node>(); this.childList = new HashSet<>();
} }
public Set<Node> getChildList() { public Set<Node> getChildList() {

View File

@ -43,9 +43,9 @@ public class EntranceNode extends DefaultNode {
} }
@Override @Override
public long avgRt() { public double avgRt() {
long total = 0; double total = 0;
long totalQps = 0; double totalQps = 0;
for (Node node : getChildList()) { for (Node node : getChildList()) {
total += node.avgRt() * node.passQps(); total += node.avgRt() * node.passQps();
totalQps += node.passQps(); totalQps += node.passQps();
@ -54,8 +54,8 @@ public class EntranceNode extends DefaultNode {
} }
@Override @Override
public long blockQps() { public double blockQps() {
long blockQps = 0; double blockQps = 0;
for (Node node : getChildList()) { for (Node node : getChildList()) {
blockQps += node.blockQps(); blockQps += node.blockQps();
} }
@ -81,8 +81,8 @@ public class EntranceNode extends DefaultNode {
} }
@Override @Override
public long totalQps() { public double totalQps() {
long r = 0; double r = 0;
for (Node node : getChildList()) { for (Node node : getChildList()) {
r += node.totalQps(); r += node.totalQps();
} }
@ -90,8 +90,8 @@ public class EntranceNode extends DefaultNode {
} }
@Override @Override
public long successQps() { public double successQps() {
long r = 0; double r = 0;
for (Node node : getChildList()) { for (Node node : getChildList()) {
r += node.successQps(); r += node.successQps();
} }
@ -99,8 +99,8 @@ public class EntranceNode extends DefaultNode {
} }
@Override @Override
public long passQps() { public double passQps() {
long r = 0; double r = 0;
for (Node node : getChildList()) { for (Node node : getChildList()) {
r += node.passQps(); r += node.passQps();
} }
@ -116,4 +116,12 @@ public class EntranceNode extends DefaultNode {
return r; return r;
} }
@Override
public long totalPass() {
long r = 0;
for (Node node : getChildList()) {
r += node.totalPass();
}
return r;
}
} }

View File

@ -19,98 +19,125 @@ import java.util.Map;
import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.node.metric.MetricNode; import com.alibaba.csp.sentinel.node.metric.MetricNode;
import com.alibaba.csp.sentinel.slots.statistic.metric.DebugSupport;
/** /**
* This class holds real-time statistics for a resource. * Holds real-time statistics for resources.
* *
* @author qinan.qn * @author qinan.qn
* @author leyou * @author leyou
* @author Eric Zhao * @author Eric Zhao
*/ */
public interface Node { public interface Node extends DebugSupport {
/** /**
* Get incoming request per minute. {@code pass + block} * Get incoming request per minute ({@code pass + block}).
*
* @return total request count per minute
*/ */
long totalRequest(); long totalRequest();
/**
* Get pass count per minute.
*
* @return total passed request count per minute
* @since 1.5.0
*/
long totalPass();
/** /**
* Get {@link Entry#exit()} count per minute. * Get {@link Entry#exit()} count per minute.
* *
* @return Outgoing request per minute. * @return total completed request count per minute
*/ */
long totalSuccess(); long totalSuccess();
/** /**
* Get block request count per minute. * Get blocked request count per minute (totalBlockRequest).
*
* @return total blocked request count per minute
*/ */
long blockRequest(); long blockRequest();
/** /**
* Get exception count per minute. * Get exception count per minute.
*
* @return total business exception count per minute
*/ */
long totalException(); long totalException();
/** /**
* Get pass request per second. * Get pass request per second.
*
* @return QPS of passed requests
*/ */
long passQps(); double passQps();
/** /**
* Get block request per second. * Get block request per second.
*
* @return QPS of blocked requests
*/ */
long blockQps(); double blockQps();
/** /**
* Get {@link #passQps()} + {@link #blockQps()} request per second. * Get {@link #passQps()} + {@link #blockQps()} request per second.
*
* @return QPS of passed and blocked requests
*/ */
long totalQps(); double totalQps();
/** /**
* Get {@link Entry#exit()} request per second. * Get {@link Entry#exit()} request per second.
*
* @return QPS of completed requests
*/ */
long successQps(); double successQps();
/** /**
* Get estimated max success QPS till now. * Get estimated max success QPS till now.
* *
* @return max success QPS * @return max completed QPS
*/ */
long maxSuccessQps(); double maxSuccessQps();
/** /**
* Get exception count per second. * Get exception count per second.
*
* @return QPS of exception occurs
*/ */
long exceptionQps(); double exceptionQps();
/** /**
* Get average rt per second. * Get average rt per second.
* *
* @return average response time per second * @return average response time per second
*/ */
long avgRt(); double avgRt();
/** /**
* Get minimal response time. * Get minimal response time.
* *
* @return recorded minimal response time * @return recorded minimal response time
*/ */
long minRt(); double minRt();
/** /**
* Get current active thread count. * Get current active thread count.
*
* @return current active thread count
*/ */
int curThreadNum(); int curThreadNum();
/** /**
* Get last second block QPS. * Get last second block QPS.
*/ */
long previousBlockQps(); double previousBlockQps();
/** /**
* Last window QPS. * Last window QPS.
*/ */
long previousPassQps(); double previousPassQps();
/** /**
* Fetch all valid metric nodes of resources. * Fetch all valid metric nodes of resources.
@ -129,18 +156,22 @@ public interface Node {
/** /**
* Add rt and success count. * Add rt and success count.
* *
* @param rt response time * @param rt response time
* @param success success count to add * @param success success count to add
*/ */
void addRtAndSuccess(long rt, int success); void addRtAndSuccess(long rt, int success);
/** /**
* Increase the block count. * Increase the block count.
*
* @param count count to add
*/ */
void increaseBlockQps(int count); void increaseBlockQps(int count);
/** /**
* Increase the biz exception count. * Add the biz exception count.
*
* @param count count to add
*/ */
void increaseExceptionQps(int count); void increaseExceptionQps(int count);
@ -159,9 +190,4 @@ public interface Node {
* {@link SampleCountProperty#SAMPLE_COUNT} is changed. * {@link SampleCountProperty#SAMPLE_COUNT} is changed.
*/ */
void reset(); void reset();
/**
* Debug only.
*/
void debug();
} }

View File

@ -151,28 +151,33 @@ public class StatisticNode implements Node {
return totalRequest; return totalRequest;
} }
@Override
public long totalPass() {
return rollingCounterInMinute.pass();
}
@Override @Override
public long blockRequest() { public long blockRequest() {
return rollingCounterInMinute.block(); return rollingCounterInMinute.block();
} }
@Override @Override
public long blockQps() { public double blockQps() {
return rollingCounterInSecond.block() / (long) rollingCounterInSecond.getWindowIntervalInSec(); return rollingCounterInSecond.block() / rollingCounterInSecond.getWindowIntervalInSec();
} }
@Override @Override
public long previousBlockQps() { public double previousBlockQps() {
return this.rollingCounterInMinute.previousWindowBlock(); return this.rollingCounterInMinute.previousWindowBlock();
} }
@Override @Override
public long previousPassQps() { public double previousPassQps() {
return this.rollingCounterInMinute.previousWindowPass(); return this.rollingCounterInMinute.previousWindowPass();
} }
@Override @Override
public long totalQps() { public double totalQps() {
return passQps() + blockQps(); return passQps() + blockQps();
} }
@ -182,8 +187,8 @@ public class StatisticNode implements Node {
} }
@Override @Override
public long exceptionQps() { public double exceptionQps() {
return rollingCounterInSecond.exception() / (long) rollingCounterInSecond.getWindowIntervalInSec(); return rollingCounterInSecond.exception() / rollingCounterInSecond.getWindowIntervalInSec();
} }
@Override @Override
@ -192,32 +197,32 @@ public class StatisticNode implements Node {
} }
@Override @Override
public long passQps() { public double passQps() {
return rollingCounterInSecond.pass() / (long) rollingCounterInSecond.getWindowIntervalInSec(); return rollingCounterInSecond.pass() / rollingCounterInSecond.getWindowIntervalInSec();
} }
@Override @Override
public long successQps() { public double successQps() {
return rollingCounterInSecond.success() / (long) rollingCounterInSecond.getWindowIntervalInSec(); return rollingCounterInSecond.success() / rollingCounterInSecond.getWindowIntervalInSec();
} }
@Override @Override
public long maxSuccessQps() { public double maxSuccessQps() {
return rollingCounterInSecond.maxSuccess() * rollingCounterInSecond.getSampleCount(); return rollingCounterInSecond.maxSuccess() * rollingCounterInSecond.getSampleCount();
} }
@Override @Override
public long avgRt() { public double avgRt() {
long successCount = rollingCounterInSecond.success(); long successCount = rollingCounterInSecond.success();
if (successCount == 0) { if (successCount == 0) {
return 0; return 0;
} }
return rollingCounterInSecond.rt() / successCount; return rollingCounterInSecond.rt() * 1.0 / successCount;
} }
@Override @Override
public long minRt() { public double minRt() {
return rollingCounterInSecond.minRt(); return rollingCounterInSecond.minRt();
} }

View File

@ -184,7 +184,7 @@ public class DegradeRule extends AbstractRule {
} else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) { } else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {
double exception = clusterNode.exceptionQps(); double exception = clusterNode.exceptionQps();
double success = clusterNode.successQps(); double success = clusterNode.successQps();
long total = clusterNode.totalQps(); double total = clusterNode.totalQps();
// if total qps less than RT_MAX_EXCEED_N, pass. // if total qps less than RT_MAX_EXCEED_N, pass.
if (total < RT_MAX_EXCEED_N) { if (total < RT_MAX_EXCEED_N) {
return true; return true;

View File

@ -112,9 +112,9 @@ public class WarmUpController implements TrafficShapingController {
@Override @Override
public boolean canPass(Node node, int acquireCount, boolean prioritized) { public boolean canPass(Node node, int acquireCount, boolean prioritized) {
long passQps = node.passQps(); long passQps = (long) node.passQps();
long previousQps = node.previousPassQps(); long previousQps = (long) node.previousPassQps();
syncToken(previousQps); syncToken(previousQps);
// 开始计算它的斜率 // 开始计算它的斜率

View File

@ -22,19 +22,16 @@ import com.alibaba.csp.sentinel.util.TimeUtil;
/** /**
* @author jialiang.linjl * @author jialiang.linjl
* @since 1.4.0
*/ */
public class WarmUpRateLimiterController extends WarmUpController { public class WarmUpRateLimiterController extends WarmUpController {
final int timeOutInMs; private final int timeoutInMs;
final AtomicLong latestPassedTime = new AtomicLong(-1); private final AtomicLong latestPassedTime = new AtomicLong(-1);
/**
* @param count
* @param warmUpPeriodSec
*/
public WarmUpRateLimiterController(double count, int warmUpPeriodSec, int timeOutMs, int coldFactor) { public WarmUpRateLimiterController(double count, int warmUpPeriodSec, int timeOutMs, int coldFactor) {
super(count, warmUpPeriodSec, coldFactor); super(count, warmUpPeriodSec, coldFactor);
this.timeOutInMs = timeOutMs; this.timeoutInMs = timeOutMs;
} }
@Override @Override
@ -44,7 +41,7 @@ public class WarmUpRateLimiterController extends WarmUpController {
@Override @Override
public boolean canPass(Node node, int acquireCount, boolean prioritized) { public boolean canPass(Node node, int acquireCount, boolean prioritized) {
long previousQps = node.previousPassQps(); long previousQps = (long) node.previousPassQps();
syncToken(previousQps); syncToken(previousQps);
long currentTime = TimeUtil.currentTimeMillis(); long currentTime = TimeUtil.currentTimeMillis();
@ -68,13 +65,13 @@ public class WarmUpRateLimiterController extends WarmUpController {
return true; return true;
} else { } else {
long waitTime = costTime + latestPassedTime.get() - currentTime; long waitTime = costTime + latestPassedTime.get() - currentTime;
if (waitTime > timeOutInMs) { if (waitTime > timeoutInMs) {
return false; return false;
} else { } else {
long oldTime = latestPassedTime.addAndGet(costTime); long oldTime = latestPassedTime.addAndGet(costTime);
try { try {
waitTime = oldTime - TimeUtil.currentTimeMillis(); waitTime = oldTime - TimeUtil.currentTimeMillis();
if (waitTime > timeOutInMs) { if (waitTime > timeoutInMs) {
latestPassedTime.addAndGet(-costTime); latestPassedTime.addAndGet(-costTime);
return false; return false;
} }
@ -89,4 +86,3 @@ public class WarmUpRateLimiterController extends WarmUpController {
return false; return false;
} }
} }

View File

@ -0,0 +1,28 @@
/*
* 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
*
* http://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.statistic.metric;
/**
* @author Eric Zhao
* @since 1.5.0
*/
public interface DebugSupport {
/**
* For debug;
*/
void debug();
}

View File

@ -139,18 +139,18 @@ public class ClusterNodeTest {
// test count<=0, no exceptionQps added // test count<=0, no exceptionQps added
clusterNode.trace(exception, 0); clusterNode.trace(exception, 0);
clusterNode.trace(exception, -1); clusterNode.trace(exception, -1);
assertEquals(0, clusterNode.exceptionQps()); assertEquals(0, clusterNode.exceptionQps(), 0.01);
assertEquals(0, clusterNode.totalException()); assertEquals(0, clusterNode.totalException());
// test count=1, not BlockException, 1 exceptionQps added // test count=1, not BlockException, 1 exceptionQps added
clusterNode.trace(exception, 1); clusterNode.trace(exception, 1);
assertEquals(1, clusterNode.exceptionQps()); assertEquals(1, clusterNode.exceptionQps(), 0.01);
assertEquals(1, clusterNode.totalException()); assertEquals(1, clusterNode.totalException());
// test count=1, BlockException, no exceptionQps added // test count=1, BlockException, no exceptionQps added
FlowException flowException = new FlowException("flow"); FlowException flowException = new FlowException("flow");
clusterNode.trace(flowException, 1); clusterNode.trace(flowException, 1);
assertEquals(1, clusterNode.exceptionQps()); assertEquals(1, clusterNode.exceptionQps(), 0.01);
assertEquals(1, clusterNode.totalException()); assertEquals(1, clusterNode.totalException());
} }
} }

View File

@ -92,9 +92,9 @@ public class StatisticNodeTest {
tickEs.shutdown(); tickEs.shutdown();
// now no biz method execute, so there is no curThreadNum,passQps,successQps // now no biz method execute, so there is no curThreadNum,passQps,successQps
assertEquals(0, node.curThreadNum()); assertEquals(0, node.curThreadNum(), 0.01);
assertEquals(0, node.passQps()); assertEquals(0, node.passQps(), 0.01);
assertEquals(0, node.successQps()); assertEquals(0, node.successQps(), 0.01);
// note: total time cost should be controlled within 1 minute, // note: total time cost should be controlled within 1 minute,
// as the node.totalRequest() holding statistics of recent 60 seconds // as the node.totalRequest() holding statistics of recent 60 seconds
@ -105,7 +105,7 @@ public class StatisticNodeTest {
assertEquals(totalRequest, node.totalSuccess()); assertEquals(totalRequest, node.totalSuccess());
// now there are no data in time span, so the minRT should be equals to TIME_DROP_VALVE // now there are no data in time span, so the minRT should be equals to TIME_DROP_VALVE
assertEquals(node.minRt(), Constants.TIME_DROP_VALVE); assertEquals(node.minRt(), Constants.TIME_DROP_VALVE, 0.01);
log("===================================================="); log("====================================================");
log("testStatisticThreadNumAndQps done, cost " + (TimeUtil.currentTimeMillis() - testStartTime) + "ms"); log("testStatisticThreadNumAndQps done, cost " + (TimeUtil.currentTimeMillis() - testStartTime) + "ms");

View File

@ -45,7 +45,7 @@ public class DegradeTest {
Context context = mock(Context.class); Context context = mock(Context.class);
DefaultNode node = mock(DefaultNode.class); DefaultNode node = mock(DefaultNode.class);
when(node.getClusterNode()).thenReturn(cn); when(node.getClusterNode()).thenReturn(cn);
when(cn.avgRt()).thenReturn(2L); when(cn.avgRt()).thenReturn(2d);
DegradeRule rule = new DegradeRule(); DegradeRule rule = new DegradeRule();
rule.setCount(1); rule.setCount(1);
@ -69,9 +69,9 @@ public class DegradeTest {
public void testExceptionRatioModeDegrade() throws Throwable { public void testExceptionRatioModeDegrade() throws Throwable {
String key = "test_degrade_exception_ratio"; String key = "test_degrade_exception_ratio";
ClusterNode cn = mock(ClusterNode.class); ClusterNode cn = mock(ClusterNode.class);
when(cn.exceptionQps()).thenReturn(2L); when(cn.exceptionQps()).thenReturn(2d);
// Indicates that there are QPS more than min threshold. // Indicates that there are QPS more than min threshold.
when(cn.totalQps()).thenReturn(12L); when(cn.totalQps()).thenReturn(12d);
ClusterBuilderSlot.getClusterNodeMap().put(new StringResourceWrapper(key, EntryType.IN), cn); ClusterBuilderSlot.getClusterNodeMap().put(new StringResourceWrapper(key, EntryType.IN), cn);
Context context = mock(Context.class); Context context = mock(Context.class);
@ -84,7 +84,7 @@ public class DegradeTest {
rule.setTimeWindow(2); rule.setTimeWindow(2);
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO); rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
when(cn.successQps()).thenReturn(8L); when(cn.successQps()).thenReturn(8d);
// Will fail. // Will fail.
assertFalse(rule.passCheck(context, node, 1)); assertFalse(rule.passCheck(context, node, 1));
@ -92,7 +92,7 @@ public class DegradeTest {
// Restore from the degrade timeout. // Restore from the degrade timeout.
TimeUnit.MILLISECONDS.sleep(2200); TimeUnit.MILLISECONDS.sleep(2200);
when(cn.successQps()).thenReturn(20L); when(cn.successQps()).thenReturn(20d);
// Will pass. // Will pass.
assertTrue(rule.passCheck(context, node, 1)); assertTrue(rule.passCheck(context, node, 1));
} }

View File

@ -18,9 +18,12 @@ package com.alibaba.csp.sentinel.slots.block.flow;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.Entry;
@ -34,6 +37,16 @@ import com.alibaba.csp.sentinel.slots.block.RuleConstant;
*/ */
public class FlowPartialIntegrationTest { public class FlowPartialIntegrationTest {
@Before
public void setUp() throws Exception {
FlowRuleManager.loadRules(new ArrayList<FlowRule>());
}
@After
public void tearDown() throws Exception {
FlowRuleManager.loadRules(new ArrayList<FlowRule>());
}
@Test @Test
public void testQPSGrade() { public void testQPSGrade() {
FlowRule flowRule = new FlowRule(); FlowRule flowRule = new FlowRule();

View File

@ -15,7 +15,7 @@
*/ */
package com.alibaba.csp.sentinel.slots.block.flow; package com.alibaba.csp.sentinel.slots.block.flow;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.*;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -52,15 +52,15 @@ public class FlowRuleTest {
when(context.getOrigin()).thenReturn(""); when(context.getOrigin()).thenReturn("");
when(node.getClusterNode()).thenReturn(cn); when(node.getClusterNode()).thenReturn(cn);
when(cn.passQps()).thenReturn(1l); when(cn.passQps()).thenReturn(1d);
assertTrue(flowRule.passCheck(context, node, 1, new Object[0]) == false); assertFalse(flowRule.passCheck(context, node, 1));
flowRule.setGrade(RuleConstant.FLOW_GRADE_THREAD); flowRule.setGrade(RuleConstant.FLOW_GRADE_THREAD);
defaultController = new DefaultController(1, flowRule.getGrade()); defaultController = new DefaultController(1, flowRule.getGrade());
flowRule.setRater(defaultController); flowRule.setRater(defaultController);
when(cn.curThreadNum()).thenReturn(1); when(cn.curThreadNum()).thenReturn(1);
assertTrue(flowRule.passCheck(context, node, 1, new Object[0]) == false); assertTrue(!flowRule.passCheck(context, node, 1));
} }
@Test @Test
@ -79,17 +79,16 @@ public class FlowRuleTest {
DefaultNode dn = mock(DefaultNode.class); DefaultNode dn = mock(DefaultNode.class);
when(context.getName()).thenReturn("entry1"); when(context.getName()).thenReturn("entry1");
when(dn.passQps()).thenReturn(1l); when(dn.passQps()).thenReturn(1d);
assertTrue(flowRule.passCheck(context, dn, 1, new Object[0]) == false); assertFalse(flowRule.passCheck(context, dn, 1));
when(context.getName()).thenReturn("entry2"); when(context.getName()).thenReturn("entry2");
assertTrue(flowRule.passCheck(context, dn, 1, new Object[0])); assertTrue(flowRule.passCheck(context, dn, 1));
// Strategy == relate // Strategy == relate
flowRule.setStrategy(RuleConstant.STRATEGY_CHAIN); flowRule.setStrategy(RuleConstant.STRATEGY_CHAIN);
ClusterNode cn = mock(ClusterNode.class); ClusterNode cn = mock(ClusterNode.class);
assertTrue(flowRule.passCheck(context, dn, 1, new Object[0]) == true); assertTrue(flowRule.passCheck(context, dn, 1));
} }
@Test @Test
@ -106,7 +105,7 @@ public class FlowRuleTest {
Context context = mock(Context.class); Context context = mock(Context.class);
DefaultNode dn = mock(DefaultNode.class); DefaultNode dn = mock(DefaultNode.class);
when(context.getOrigin()).thenReturn("origin1"); when(context.getOrigin()).thenReturn("origin1");
when(dn.passQps()).thenReturn(1l); when(dn.passQps()).thenReturn(1d);
when(context.getOriginNode()).thenReturn(dn); when(context.getOriginNode()).thenReturn(dn);
/* /*
@ -115,9 +114,9 @@ public class FlowRuleTest {
*/ */
ClusterNode cn = mock(ClusterNode.class); ClusterNode cn = mock(ClusterNode.class);
when(dn.getClusterNode()).thenReturn(cn); when(dn.getClusterNode()).thenReturn(cn);
when(cn.passQps()).thenReturn(1l); when(cn.passQps()).thenReturn(1d);
assertTrue(flowRule.passCheck(context, dn, 1, new Object[0]) == false); assertTrue(flowRule.passCheck(context, dn, 1, new Object[0]) == false);
when(cn.passQps()).thenReturn(0l); when(cn.passQps()).thenReturn(0d);
assertTrue(flowRule.passCheck(context, dn, 1, new Object[0])); assertTrue(flowRule.passCheck(context, dn, 1, new Object[0]));
flowRule.setStrategy(RuleConstant.STRATEGY_CHAIN); flowRule.setStrategy(RuleConstant.STRATEGY_CHAIN);

View File

@ -16,7 +16,7 @@ public class DefaultControllerTest {
@Test @Test
public void testCanPassForQps() { public void testCanPassForQps() {
long threshold = 10; double threshold = 10;
TrafficShapingController controller = new DefaultController(threshold, RuleConstant.FLOW_GRADE_QPS); TrafficShapingController controller = new DefaultController(threshold, RuleConstant.FLOW_GRADE_QPS);
Node node = mock(Node.class); Node node = mock(Node.class);
when(node.passQps()).thenReturn(threshold - 1) when(node.passQps()).thenReturn(threshold - 1)

View File

@ -38,26 +38,26 @@ public class WarmUpControllerTest extends AbstractTimeBasedTest {
Node node = mock(Node.class); Node node = mock(Node.class);
when(node.passQps()).thenReturn(8L); when(node.passQps()).thenReturn(8d);
when(node.previousPassQps()).thenReturn(1L); when(node.previousPassQps()).thenReturn(1d);
assertFalse(warmupController.canPass(node, 1)); assertFalse(warmupController.canPass(node, 1));
when(node.passQps()).thenReturn(1L); when(node.passQps()).thenReturn(1d);
when(node.previousPassQps()).thenReturn(1L); when(node.previousPassQps()).thenReturn(1d);
assertTrue(warmupController.canPass(node, 1)); assertTrue(warmupController.canPass(node, 1));
when(node.previousPassQps()).thenReturn(10L); when(node.previousPassQps()).thenReturn(10d);
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
sleep(100); sleep(100);
warmupController.canPass(node, 1); warmupController.canPass(node, 1);
} }
when(node.passQps()).thenReturn(8L); when(node.passQps()).thenReturn(8d);
assertTrue(warmupController.canPass(node, 1)); assertTrue(warmupController.canPass(node, 1));
when(node.passQps()).thenReturn(10L); when(node.passQps()).thenReturn(10d);
assertFalse(warmupController.canPass(node, 1)); assertFalse(warmupController.canPass(node, 1));
} }
} }

View File

@ -22,15 +22,15 @@ public class WarmUpRateLimiterControllerTest {
Node node = mock(Node.class); Node node = mock(Node.class);
when(node.passQps()).thenReturn(100L); when(node.passQps()).thenReturn(100d);
when(node.previousPassQps()).thenReturn(100L); when(node.previousPassQps()).thenReturn(100d);
assertTrue(controller.canPass(node, 1)); assertTrue(controller.canPass(node, 1));
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
assertTrue(controller.canPass(node, 1)); assertTrue(controller.canPass(node, 1));
long cost = System.currentTimeMillis() - start; long cost = System.currentTimeMillis() - start;
assertTrue(cost >= 100 && cost <= 110); assertTrue(cost >= 100 && cost <= 120);
} }
@Test @Test
@ -39,8 +39,8 @@ public class WarmUpRateLimiterControllerTest {
Node node = mock(Node.class); Node node = mock(Node.class);
when(node.passQps()).thenReturn(100L); when(node.passQps()).thenReturn(100d);
when(node.previousPassQps()).thenReturn(100L); when(node.previousPassQps()).thenReturn(100d);
assertTrue(controller.canPass(node, 1)); assertTrue(controller.canPass(node, 1));

View File

@ -63,12 +63,12 @@ public class NodeVo {
vo.parentId = parentId; vo.parentId = parentId;
vo.resource = node.getId().getShowName(); vo.resource = node.getId().getShowName();
vo.threadNum = node.curThreadNum(); vo.threadNum = node.curThreadNum();
vo.passQps = node.passQps(); vo.passQps = (long) node.passQps();
vo.blockQps = node.blockQps(); vo.blockQps = (long) node.blockQps();
vo.totalQps = node.totalQps(); vo.totalQps = (long) node.totalQps();
vo.averageRt = node.avgRt(); vo.averageRt = (long) node.avgRt();
vo.successQps = node.successQps(); vo.successQps = (long) node.successQps();
vo.exceptionQps = node.exceptionQps(); vo.exceptionQps = (long) node.exceptionQps();
vo.oneMinuteException = node.totalException(); vo.oneMinuteException = node.totalException();
vo.oneMinutePass = node.totalRequest() - node.blockRequest(); vo.oneMinutePass = node.totalRequest() - node.blockRequest();
vo.oneMinuteBlock = node.blockRequest(); vo.oneMinuteBlock = node.blockRequest();
@ -102,12 +102,12 @@ public class NodeVo {
NodeVo vo = new NodeVo(); NodeVo vo = new NodeVo();
vo.resource = name; vo.resource = name;
vo.threadNum = node.curThreadNum(); vo.threadNum = node.curThreadNum();
vo.passQps = node.passQps(); vo.passQps = (long) node.passQps();
vo.blockQps = node.blockQps(); vo.blockQps = (long) node.blockQps();
vo.totalQps = node.totalQps(); vo.totalQps = (long) node.totalQps();
vo.averageRt = node.avgRt(); vo.averageRt = (long) node.avgRt();
vo.successQps = node.successQps(); vo.successQps = (long) node.successQps();
vo.exceptionQps = node.exceptionQps(); vo.exceptionQps = (long) node.exceptionQps();
vo.oneMinuteException = node.totalException(); vo.oneMinuteException = node.totalException();
vo.oneMinutePass = node.totalRequest() - node.blockRequest(); vo.oneMinutePass = node.totalRequest() - node.blockRequest();
vo.oneMinuteBlock = node.blockRequest(); vo.oneMinuteBlock = node.blockRequest();