下面列出了org.springframework.boot.actuate.endpoint.annotation.ReadOperation#com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Test
public void testFetchActiveRuleCommandSomeFlowRules() {
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule rule1 = new FlowRule();
rule1.setResource("key");
rule1.setCount(20);
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setLimitApp("default");
rules.add(rule1);
FlowRuleManager.loadRules(rules);
String httpRequestStr = "GET /getRules?type=flow HTTP/1.1" + CRLF
+ "Host: localhost:8719" + CRLF
+ CRLF;
// body json
/*
String expectedBody = "[{\"clusterMode\":false,\"controlBehavior\":0,\"count\":20.0"
+ ",\"grade\":1,\"limitApp\":\"default\",\"maxQueueingTimeMs\":500"
+ ",\"resource\":\"key\",\"strategy\":0,\"warmUpPeriodSec\":10}]";
*/
String expectedBody = JSON.toJSONString(rules);
processSuccess(httpRequestStr, expectedBody);
}
private void listenRules() throws Exception {
ClassLoader classLoader = getClass().getClassLoader();
String flowRulePath = URLDecoder.decode(classLoader.getResource("FlowRule.json").getFile(), "UTF-8");
String degradeRulePath = URLDecoder.decode(classLoader.getResource("DegradeRule.json").getFile(), "UTF-8");
String systemRulePath = URLDecoder.decode(classLoader.getResource("SystemRule.json").getFile(), "UTF-8");
// Data source for FlowRule
FileRefreshableDataSource<List<FlowRule>> flowRuleDataSource = new FileRefreshableDataSource<>(
flowRulePath, flowRuleListParser);
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
// Data source for DegradeRule
FileRefreshableDataSource<List<DegradeRule>> degradeRuleDataSource
= new FileRefreshableDataSource<>(
degradeRulePath, degradeRuleListParser);
DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());
// Data source for SystemRule
FileRefreshableDataSource<List<SystemRule>> systemRuleDataSource
= new FileRefreshableDataSource<>(
systemRulePath, systemRuleListParser);
SystemRuleManager.register2Property(systemRuleDataSource.getProperty());
}
private static void initPaceFlowRule() {
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule rule1 = new FlowRule();
rule1.setResource(KEY);
rule1.setCount(count);
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setLimitApp("default");
/*
* CONTROL_BEHAVIOR_RATE_LIMITER means requests more than threshold will be queueing in the queue,
* until the queueing time is more than {@link FlowRule#maxQueueingTimeMs}, the requests will be rejected.
*/
rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);
rule1.setMaxQueueingTimeMs(20 * 1000);
rules.add(rule1);
FlowRuleManager.loadRules(rules);
}
@Test
public void testDefaultFallbackWithSingleParam() {
assertThat(fooService.anotherFoo(1)).isEqualTo("Hello for 1");
String resourceName = "apiAnotherFooWithDefaultFallback";
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertThat(cn).isNotNull();
assertThat(cn.passQps()).isPositive();
// Default fallback should take effect.
assertThat(fooService.anotherFoo(5758)).isEqualTo(FooUtil.FALLBACK_DEFAULT_RESULT);
assertThat(cn.exceptionQps()).isPositive();
assertThat(cn.blockQps()).isZero();
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
// Default fallback should also take effect for BlockException.
assertThat(fooService.anotherFoo(5758)).isEqualTo(FooUtil.FALLBACK_DEFAULT_RESULT);
assertThat(cn.blockQps()).isPositive();
}
private static void loadRules() {
// Set up basic information, only for demo purpose. You may adjust them based on your actual environment.
// For more information, please refer https://github.com/ctripcorp/apollo
String appId = "sentinel-demo";
String apolloMetaServerAddress = "http://localhost:8080";
System.setProperty("app.id", appId);
System.setProperty("apollo.meta", apolloMetaServerAddress);
String namespaceName = "application";
String flowRuleKey = "flowRules";
// It's better to provide a meaningful default value.
String defaultFlowRules = "[]";
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ApolloDataSource<>(namespaceName,
flowRuleKey, defaultFlowRules, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}
private static void initFlowControlRule() {
FlowRule rule = new FlowRule();
rule.setResource(KEY);
// Indicates the interval between two adjacent requests is 200 ms.
rule.setCount(5);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setLimitApp("default");
// Enable rate limiting (uniform). This can ensure fixed intervals between two adjacent calls.
// In this example, intervals between two incoming calls (message consumption) will be 200 ms constantly.
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);
// If more requests are coming, they'll be put into the waiting queue.
// The queue has a queueing timeout. Requests that may exceed the timeout will be immediately blocked.
// In this example, the max timeout is 5s.
rule.setMaxQueueingTimeMs(5 * 1000);
FlowRuleManager.loadRules(Collections.singletonList(rule));
}
@Test
public void testReactorEntryNormalWhenFlowControlTriggered() {
String resourceName = createResourceName("testReactorEntryNormalWhenFlowControlTriggered");
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
StepVerifier.create(ReactorSphU.entryWith(resourceName, Mono.just(60))
.subscribeOn(Schedulers.elastic())
.map(e -> e * 3))
.expectError(BlockException.class)
.verify();
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertNotNull(cn);
assertEquals(0, cn.passQps(), 0.01);
assertEquals(1, cn.blockRequest());
FlowRuleManager.loadRules(new ArrayList<>());
}
@Test
public void testEmitSingleValueWhenFlowControlTriggered() {
String resourceName = createResourceName("testEmitSingleValueWhenFlowControlTriggered");
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
StepVerifier.create(Mono.just(1)
.map(e -> e * 2)
.transform(new SentinelReactorTransformer<>(resourceName)))
.expectError(BlockException.class)
.verify();
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertNotNull(cn);
assertEquals(0, cn.passQps(), 0.01);
assertEquals(1, cn.blockRequest());
FlowRuleManager.loadRules(new ArrayList<>());
}
private void testCommonBlockAndRedirectBlockPage(String url, ClusterNode cnGet, ClusterNode cnPost) throws Exception {
configureRulesFor(GET + ":" + url, 0);
// The request will be blocked and response is default block message.
this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().string(FilterUtil.DEFAULT_BLOCK_MSG));
assertEquals(1, cnGet.blockQps(), 0.01);
// Test for post pass
this.mvc.perform(post(url))
.andExpect(status().isOk())
.andExpect(content().string(HELLO_POST_STR));
assertEquals(2, cnPost.passQps(), 0.01);
FlowRuleManager.loadRules(null);
WebServletConfig.setBlockPage("");
}
@Test
public void testEmitExceptionWhenFlowControlTriggered() {
String resourceName = createResourceName("testEmitExceptionWhenFlowControlTriggered");
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
StepVerifier.create(Mono.error(new IllegalStateException("some"))
.transform(new SentinelReactorTransformer<>(resourceName)))
.expectError(BlockException.class)
.verify();
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertNotNull(cn);
assertEquals(0, cn.passQps(), 0.01);
assertEquals(1, cn.blockRequest());
FlowRuleManager.loadRules(new ArrayList<>());
}
@Test
public void testDefaultFallbackWithSingleParam() {
assertThat(fooService.anotherFoo(1)).isEqualTo("Hello for 1");
String resourceName = "apiAnotherFooWithDefaultFallback";
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertThat(cn).isNotNull();
assertThat(cn.passQps()).isPositive();
// Default fallback should take effect.
assertThat(fooService.anotherFoo(5758)).isEqualTo(FooUtil.FALLBACK_DEFAULT_RESULT);
assertThat(cn.exceptionQps()).isPositive();
assertThat(cn.blockQps()).isZero();
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
// Default fallback should also take effect for BlockException.
assertThat(fooService.anotherFoo(5758)).isEqualTo(FooUtil.FALLBACK_DEFAULT_RESULT);
assertThat(cn.blockQps()).isPositive();
}
private static void loadRules() {
// Set up basic information, only for demo purpose. You may adjust them based on your actual environment.
// For more information, please refer https://github.com/ctripcorp/apollo
String appId = "sentinel-demo";
String apolloMetaServerAddress = "http://localhost:8080";
System.setProperty("app.id", appId);
System.setProperty("apollo.meta", apolloMetaServerAddress);
String namespaceName = "application";
String flowRuleKey = "flowRules";
// It's better to provide a meaningful default value.
String defaultFlowRules = "[]";
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ApolloDataSource<>(namespaceName,
flowRuleKey, defaultFlowRules, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}
@Test
public void testEmitMultipleValuesWhenFlowControlTriggered() {
String resourceName = createResourceName("testEmitMultipleValuesWhenFlowControlTriggered");
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
StepVerifier.create(Flux.just(1, 3, 5)
.map(e -> e * 2)
.transform(new SentinelReactorTransformer<>(resourceName)))
.expectError(BlockException.class)
.verify();
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertNotNull(cn);
assertEquals(0, cn.passQps(), 0.01);
assertEquals(1, cn.blockRequest());
FlowRuleManager.loadRules(new ArrayList<>());
}
@Test
public void testDefaultFallbackWithSingleParam() {
assertThat(fooService.anotherFoo(1)).isEqualTo("Hello for 1");
String resourceName = "apiAnotherFooWithDefaultFallback";
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertThat(cn).isNotNull();
assertThat(cn.passQps()).isPositive();
// Default fallback should take effect.
assertThat(fooService.anotherFoo(5758)).isEqualTo(FooUtil.FALLBACK_DEFAULT_RESULT);
assertThat(cn.exceptionQps()).isPositive();
assertThat(cn.blockQps()).isZero();
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
// Default fallback should also take effect for BlockException.
assertThat(fooService.anotherFoo(5758)).isEqualTo(FooUtil.FALLBACK_DEFAULT_RESULT);
assertThat(cn.blockQps()).isPositive();
}
@Test
public void testBlockHandlerNotFound() {
assertThat(fooService.baz("Sentinel")).isEqualTo("cheers, Sentinel");
String resourceName = "apiBaz";
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertThat(cn).isNotNull();
assertThat(cn.passQps()).isPositive();
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
Assertions.assertThrows(ArcUndeclaredThrowableException.class, () -> {
fooService.baz("Sentinel");
});
}
@Override
public void init() throws Exception {
// A fake path.
String flowRuleDir = System.getProperty("user.home") + File.separator + "sentinel" + File.separator + "rules";
String flowRuleFile = "flowRule.json";
String flowRulePath = flowRuleDir + File.separator + flowRuleFile;
ReadableDataSource<String, List<FlowRule>> ds = new FileRefreshableDataSource<>(
flowRulePath, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {})
);
// Register to flow rule manager.
FlowRuleManager.register2Property(ds.getProperty());
WritableDataSource<List<FlowRule>> wds = new FileWritableDataSource<>(flowRulePath, this::encodeJson);
// Register to writable data source registry so that rules can be updated to file
// when there are rules pushed from the Sentinel Dashboard.
WritableDataSourceRegistry.registerFlowDataSource(wds);
}
public static void main(String[] args) {
String rule_key = "sentinel_demo_rule_key";
String yourUserName = "root";
String yourPassWord = "12345";
String endPoints = "http://127.0.0.1:2379";
SentinelConfig.setConfig(EtcdConfig.END_POINTS, endPoints);
SentinelConfig.setConfig(EtcdConfig.USER, yourUserName);
SentinelConfig.setConfig(EtcdConfig.PASSWORD, yourPassWord);
SentinelConfig.setConfig(EtcdConfig.CHARSET, "utf-8");
SentinelConfig.setConfig(EtcdConfig.AUTH_ENABLE, "true");
ReadableDataSource<String, List<FlowRule>> flowRuleEtcdDataSource = new EtcdDataSource<>(rule_key, (rule) -> JSON.parseArray(rule, FlowRule.class));
FlowRuleManager.register2Property(flowRuleEtcdDataSource.getProperty());
List<FlowRule> rules = FlowRuleManager.getRules();
System.out.println(rules);
}
@Before
public void before() {
// The same Handlers in order as the ChannelPipeline in HttpServerInitializer
HttpRequestDecoder httpRequestDecoder = new HttpRequestDecoder();
HttpObjectAggregator httpObjectAggregator = new HttpObjectAggregator(1024 * 1024);
HttpResponseEncoder httpResponseEncoder = new HttpResponseEncoder();
HttpServerHandler httpServerHandler = new HttpServerHandler();
// Create new EmbeddedChannel every method call
embeddedChannel = new EmbeddedChannel(httpRequestDecoder, httpObjectAggregator, httpResponseEncoder, httpServerHandler);
// Clear flow rules
FlowRuleManager.loadRules(Collections.EMPTY_LIST);
}
private static void initFlowRule() {
FlowRule flowRule = new FlowRule();
flowRule.setResource(RES_KEY);
flowRule.setCount(5);
flowRule.setGrade(RuleConstant.FLOW_GRADE_THREAD);
flowRule.setLimitApp("default");
FlowRuleManager.loadRules(Collections.singletonList(flowRule));
}
private static void initFlowRule() {
FlowRule flowRule = new FlowRule();
flowRule.setResource(RES_KEY);
flowRule.setCount(10);
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
flowRule.setLimitApp("default");
FlowRuleManager.loadRules(Collections.singletonList(flowRule));
}
private void listenRules() throws Exception {
// Modify the path with your real path.
String jarPath = System.getProperty("user.dir") + "/sentinel-demo/sentinel-demo-dynamic-file-rule/target/"
+ "sentinel-demo-dynamic-file-rule.jar";
// eg: if flowRuleInJarName full path is 'sentinel-demo-dynamic-file-rule.jar!/classes/FlowRule.json',
// your flowRuleInJarName is 'classes/FlowRule.json'
String flowRuleInJarPath = "FlowRule.json";
FileInJarReadableDataSource<List<FlowRule>> flowRuleDataSource = new FileInJarReadableDataSource<>(
jarPath,flowRuleInJarPath, flowRuleListParser);
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}
private void configureFlowRule(int count) {
FlowRule rule = new FlowRule()
.setCount(count)
.setGrade(RuleConstant.FLOW_GRADE_QPS)
.setResource(fullMethodName)
.setLimitApp("default")
.as(FlowRule.class);
FlowRuleManager.loadRules(Collections.singletonList(rule));
}
private static void initFlowRule() {
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule rule1 = new FlowRule();
rule1.setResource("methodA");
// set limit concurrent thread for 'methodA' to 20
rule1.setCount(20);
rule1.setGrade(RuleConstant.FLOW_GRADE_THREAD);
rule1.setLimitApp("default");
rules.add(rule1);
FlowRuleManager.loadRules(rules);
}
private static void initFlowRule() {
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule rule1 = new FlowRule();
rule1.setResource(KEY);
rule1.setCount(20);
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setLimitApp("default");
rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
rule1.setWarmUpPeriodSec(10);
rules.add(rule1);
FlowRuleManager.loadRules(rules);
}
private static void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule rule1 = new FlowRule();
rule1.setResource(KEY);
// set limit qps to 20
rule1.setCount(20);
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setLimitApp("default");
rules.add(rule1);
FlowRuleManager.loadRules(rules);
}
private static void initFlowRule() {
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule rule1 = new FlowRule();
rule1.setResource(KEY);
rule1.setCount(20);
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setLimitApp("default");
rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP_RATE_LIMITER);
rule1.setWarmUpPeriodSec(10);
rule1.setMaxQueueingTimeMs(100);
rules.add(rule1);
FlowRuleManager.loadRules(rules);
}
private void testCustomOriginParser() throws Exception {
String url = "/hello";
String limitOrigin = "userA";
final String headerName = "S-User";
configureRulesFor(url, 0, limitOrigin);
WebCallbackManager.setRequestOriginParser(new RequestOriginParser() {
@Override
public String parseOrigin(HttpServletRequest request) {
String origin = request.getHeader(headerName);
return origin != null ? origin : "";
}
});
this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN).header(headerName, "userB"))
.andExpect(status().isOk())
.andExpect(content().string(HELLO_STR));
// This will be blocked.
this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN).header(headerName, limitOrigin))
.andExpect(status().isTooManyRequests())
.andExpect(content().string(FilterUtil.DEFAULT_BLOCK_MSG));
this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().string(HELLO_STR));
WebCallbackManager.setRequestOriginParser(null);
FlowRuleManager.loadRules(null);
}
@Test
public void testFallbackWithNoParams() throws Exception {
assertThat(fooService.fooWithFallback(1)).isEqualTo("Hello for 1");
String resourceName = "apiFooWithFallback";
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertThat(cn).isNotNull();
assertThat(cn.passQps()).isPositive();
// Fallback should be ignored for this.
try {
fooService.fooWithFallback(5758);
fail("should not reach here");
} catch (IllegalAccessException e) {
assertThat(cn.exceptionQps()).isZero();
}
// Fallback should take effect.
assertThat(fooService.fooWithFallback(5763)).isEqualTo("eee...");
assertThat(cn.exceptionQps()).isPositive();
assertThat(cn.blockQps()).isZero();
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
// Fallback should not take effect for BlockException, as blockHandler is configured.
assertThat(fooService.fooWithFallback(2221)).isEqualTo("Oops, 2221");
assertThat(cn.blockQps()).isPositive();
}
private void configureRulesFor(String resource, int count, String limitApp) {
FlowRule rule = new FlowRule()
.setCount(count)
.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setResource(resource);
if (StringUtil.isNotBlank(limitApp)) {
rule.setLimitApp(limitApp);
}
FlowRuleManager.loadRules(Collections.singletonList(rule));
}
private void configureRulesFor(String resource, int count, String limitApp) {
FlowRule rule = new FlowRule()
.setCount(count)
.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setResource(resource);
if (StringUtil.isNotBlank(limitApp)) {
rule.setLimitApp(limitApp);
}
FlowRuleManager.loadRules(Collections.singletonList(rule));
}