From b374a291be06f0c8c7e10ceeb9dbd4e5cbe17e8b Mon Sep 17 00:00:00 2001 From: fangjian0423 Date: Wed, 24 Oct 2018 16:08:15 +0800 Subject: [PATCH] Add rules automation --- .../sentinel-core-example/readme-zh.md | 8 +-- .../sentinel-core-example/readme.md | 8 +-- .../src/main/resources/application.properties | 2 +- .../SentinelDataSourcePostProcessor.java | 52 +++++++++++++++++++ 4 files changed, 61 insertions(+), 9 deletions(-) diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md index 47b4a51dc..4c0b2aeba 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md @@ -192,9 +192,9 @@ Sentinel 控制台支持实时监控查看,您可以通过 Sentinel 控制台

-## DataSource 支持 +## ReadableDataSource 支持 -Sentinel 内部提供了[动态规则的扩展实现 DataSource](https://github.com/alibaba/Sentinel/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%99%E6%89%A9%E5%B1%95#datasource-%E6%89%A9%E5%B1%95)。 +Sentinel 内部提供了[动态规则的扩展实现 ReadableDataSource](https://github.com/alibaba/Sentinel/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%99%E6%89%A9%E5%B1%95#datasource-%E6%89%A9%E5%B1%95)。 Sentinel starter 整合了目前存在的几类 DataSource。只需要在配置文件中进行相关配置,即可在 Spring 容器中自动注册 DataSource。 @@ -210,7 +210,7 @@ Sentinel starter 整合了目前存在的几类 DataSource。只需要在配置 然后使用`@SentinelDataSource` 注解修饰 DataSource 即可注入: @SentinelDataSource("spring.cloud.sentinel.datasource") - private DataSource dataSource; + private ReadableDataSource dataSource; `@SentinelDataSource` 注解的 value 属性可以不填。默认值就是 `spring.cloud.sentinel.datasource`。 @@ -230,7 +230,7 @@ type目前支持file, nacos, zk, apollo。 1. 定义DataSource - public class CustomDataSource implements DataSource { + public class CustomDataSource implements ReadableDataSource { private String fieldA; private String fieldB; ... diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md index 06e189b9f..82bd95ffb 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md @@ -165,9 +165,9 @@ To see the metrics, click **实时监控(Real-time Monitoring)** in the left-sid

-## DataSource +## ReadableDataSource -Sentinel provide [DataSource](https://github.com/alibaba/Sentinel/blob/master/sentinel-extension/sentinel-datasource-extension/src/main/java/com/alibaba/csp/sentinel/datasource/DataSource.java) to manage dynamic rules. +Sentinel provide [ReadableDataSource](https://github.com/alibaba/Sentinel/blob/master/sentinel-extension/sentinel-datasource-extension/src/main/java/com/alibaba/csp/sentinel/datasource/ReadableDataSource.java) to manage dynamic rules. Sentinel starter integrated 4 DataSources provided by Sentinel. It will be register into Spring Context if you write some configs in `application.properties`. @@ -183,7 +183,7 @@ If you want to define FileRefreshableDataSource: then use `@SentinelDataSource` to annotate DataSource: @SentinelDataSource("spring.cloud.sentinel.datasource") - private DataSource dataSource; + private ReadableDataSource dataSource; The value() of `@SentinelDataSource` is not required, it means the prefix of configuration. Default value is `spring.cloud.sentinel.datasource`. @@ -201,7 +201,7 @@ User-defined DataSource need 2 steps. 1. Define DataSource - public class CustomDataSource implements DataSource { + public class CustomDataSource implements ReadableDataSource { private String fieldA; private String fieldB; ... diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties index b8ef4539f..b61171907 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties @@ -10,5 +10,5 @@ spring.cloud.sentinel.datasource.type=file spring.cloud.sentinel.datasource.recommendRefreshMs=3000 spring.cloud.sentinel.datasource.bufSize=4056196 spring.cloud.sentinel.datasource.charset=utf-8 -spring.cloud.sentinel.datasource.configParser=myParser +spring.cloud.sentinel.datasource.converter=myParser spring.cloud.sentinel.datasource.file=/Users/you/rule.json \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java index eb5cc3249..4d01ecbe3 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java @@ -36,15 +36,27 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.cloud.alibaba.sentinel.SentinelConstants; import org.springframework.cloud.alibaba.sentinel.annotation.SentinelDataSource; import org.springframework.cloud.alibaba.sentinel.util.PropertySourcesUtils; import org.springframework.context.ApplicationContext; +import org.springframework.context.event.EventListener; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.datasource.ReadableDataSource; +import com.alibaba.csp.sentinel.property.SentinelProperty; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; +import com.alibaba.csp.sentinel.slots.system.SystemRule; +import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; /** * {@link SentinelDataSource @SentinelDataSource} Post Processor @@ -187,6 +199,46 @@ public class SentinelDataSourcePostProcessor beanFactory.registerBeanDefinition(beanName, builder.getBeanDefinition()); } + @EventListener(classes = ApplicationReadyEvent.class) + public void appStartedListener(ApplicationReadyEvent event) throws Exception { + Map dataSourceMap = event.getApplicationContext().getBeansOfType(ReadableDataSource.class); + if(dataSourceMap.size() == 1) { + ReadableDataSource dataSource = dataSourceMap.values().iterator().next(); + Object ruleConfig = dataSource.loadConfig(); + SentinelProperty sentinelProperty = dataSource.getProperty(); + if(checkRuleType(ruleConfig, FlowRule.class)) { + FlowRuleManager.register2Property(sentinelProperty); + } + if(checkRuleType(ruleConfig, DegradeRule.class)) { + DegradeRuleManager.register2Property(sentinelProperty); + } + if(checkRuleType(ruleConfig, SystemRule.class)) { + SystemRuleManager.register2Property(sentinelProperty); + } + if(checkRuleType(ruleConfig, AuthorityRule.class)) { + AuthorityRuleManager.register2Property(sentinelProperty); + } + } + } + + private boolean checkRuleType(Object ruleConfig, Class type) { + if(ruleConfig.getClass() == type) { + return true; + } else if(ruleConfig instanceof List) { + List ruleList = (List)ruleConfig; + List checkList = new ArrayList(); + for(Object rule : ruleList) { + if(rule.getClass() == type) { + checkList.add(rule); + } + } + if(ruleList.size() == checkList.size()) { + return true; + } + } + return false; + } + class SentinelDataSourceField { private SentinelDataSource sentinelDataSource; private Field field;