diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml
index fad353f13..1c39170ae 100644
--- a/spring-cloud-alibaba-dependencies/pom.xml
+++ b/spring-cloud-alibaba-dependencies/pom.xml
@@ -32,6 +32,21 @@
sentinel-datasource-extension
${sentinel.version}
+
+ com.alibaba.csp
+ sentinel-datasource-apollo
+ ${sentinel.version}
+
+
+ com.alibaba.csp
+ sentinel-datasource-zookeeper
+ ${sentinel.version}
+
+
+ com.alibaba.csp
+ sentinel-datasource-nacos
+ ${sentinel.version}
+
com.alibaba.csp
sentinel-web-servlet
diff --git a/spring-cloud-alibaba-examples/pom.xml b/spring-cloud-alibaba-examples/pom.xml
index 24450ae2e..f5205129b 100644
--- a/spring-cloud-alibaba-examples/pom.xml
+++ b/spring-cloud-alibaba-examples/pom.xml
@@ -16,6 +16,9 @@
sentinel-example
+ sentinel-dubbo-provider-example
+ sentinel-dubbo-consumer-example
+ sentinel-dubbo-api
storage-example
diff --git a/spring-cloud-alibaba-examples/sentinel-example/pom.xml b/spring-cloud-alibaba-examples/sentinel-example/pom.xml
index 5348d778a..c15c79575 100644
--- a/spring-cloud-alibaba-examples/sentinel-example/pom.xml
+++ b/spring-cloud-alibaba-examples/sentinel-example/pom.xml
@@ -30,12 +30,6 @@
spring-boot-starter-actuator
-
- com.alibaba.boot
- dubbo-spring-boot-starter
- 0.1.1
-
-
diff --git a/spring-cloud-alibaba-examples/sentinel-example/readme-zh.md b/spring-cloud-alibaba-examples/sentinel-example/readme-zh.md
index 048f18c49..e39bf75d8 100644
--- a/spring-cloud-alibaba-examples/sentinel-example/readme-zh.md
+++ b/spring-cloud-alibaba-examples/sentinel-example/readme-zh.md
@@ -157,42 +157,81 @@ Sentinel 控制台支持实时监控查看,您可以通过 Sentinel 控制台

-## Dubbo支持
+## DataSource支持
-[Dubbo](http://dubbo.apache.org/)是一款高性能Java RPC框架。
+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提供了[sentinel-dubbo-adapter](https://github.com/alibaba/Sentinel/tree/master/sentinel-adapter/sentinel-dubbo-adapter)模块用来支持Dubbo服务调用的限流降级。sentinel-starter默认也集成了该功能。
+Sentinel starter整合了目前存在的4类DataSource。只需要在配置文件中进行相关配置,即可在Spring容器中自动注册DataSource。
-比如有个FooService服务,定义如下:
+比如要定义一个FileRefreshableDataSource,配置如下:
- package org.springframework.cloud.alibaba.cloud.examples.dubbo.FooService;
- public interface FooService {
- String hello(String name);
- }
+ spring.cloud.sentinel.datasource.type=file
+ spring.cloud.sentinel.datasource.recommendRefreshMs=2000
+ spring.cloud.sentinel.datasource.bufSize=2048
+ spring.cloud.sentinel.datasource.charset=utf-8
+ spring.cloud.sentinel.datasource.configParser=myParser
+ spring.cloud.sentinel.datasource.file=/Users/you/rule.json
+
+然后使用`@SentinelDataSource`注解修饰DataSource即可注入:
+
+ @SentinelDataSource("spring.cloud.sentinel.datasource")
+ private DataSource dataSource;
+
+`@SentinelDataSource`注解的value属性可以不填。默认值就是spring.cloud.sentinel.datasource。
-该服务在Sentinel下对应的资源名是 `org.springframework.cloud.alibaba.cloud.examples.dubbo.FooService:hello(java.lang.String)` 。
+value属性代表配置前缀。示例中会去找spring.cloud.sentinel.datasource.xxx相关的配置。
-在Consumer端进行限流的话,需要处理SentinelRpcException。
+spring.cloud.sentinel.datasource.type就是对应的DataSource类型。
- FooService service = applicationContext.getBean(FooService.class);
-
- for (int i = 0; i < 15; i++) {
- try {
- String message = service.hello("Jim");
- } catch (SentinelRpcException ex) {
- System.out.println("Blocked");
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
+spring.cloud.sentinel.datasource.recommendRefreshMs里的recommendRefreshMs对应相关DataSource的属性。
-在Provider端进行限流的话,Consumer端调用的话会抛出RpcException。因为Provider端被限流抛出了SentinelRpcException。
+spring.cloud.sentinel.datasource.configParser代表ConfigParser在Spring容器里的name。如果没找到,会抛出异常。
+
+type目前支持file, nacos, zk, apollo。
-### Dubbo 应用启动
+### 自定义DataSource
-在启动ServiceApplication的前提下,再启动ConsumerApplication。
+自定义DataSource只需要两部。
-ConsumerApplication在Consumer端设置了限流规则,所以启动完成后查看控制台的打印信息,会发现部分调用被Block。
+1. 定义DataSource
+
+ public class CustomDataSource implements DataSource {
+ private String fieldA;
+ private String fieldB;
+ ...
+ }
+
+2. 装配DataSource。有两种方式处理。
+
+ * 直接构造DataSource
+
+ @Bean
+ public CustomDataSource customDataSource() {
+ CustomDataSource customDataSource =
+ new CustomDataSource();
+ customDataSource.setFieldA("valueA");
+ customDataSource.setFieldB("valueB");
+ ...
+ return customDataSource;
+ }
+
+ * 在classpath:/META-INF/sentinel-datasource.properties中管理DataSource信息
+
+ custom = yourpackage.CustomDataSource
+
+ 在application.properties中定义DataSource
+
+ spring.cloud.sentinel.datasource.type = custom
+ spring.cloud.sentinel.datasource.fieldA = valueA
+ spring.cloud.sentinel.datasource.fieldB = valueB
+
+ 注意:由于目前Sentinel的AbstractDataSource需要有个ConfigParser作为构造函数中的参数,并且它的子类的构造都是通过多个参数的构造函数构造的。
+ 所以目前所有的Sentinel starter中的DataSource都是基于FactoryBean并且通过设置属性构造的。如果有这方面的需求,需要再多加一个registerFactoryBean过程。
+
+ SentinelDataSourceRegistry.registerFactoryBean("custeom", CustomDataSourceFactoryBean.class);
+
+ 如果自定义DataSource可以注入属性,那么没有必要使用SentinelDataSourceRegistry注册FactoryBean。
+
## More
Sentinel 是一款功能强大的中间件,从流量控制,熔断降级,系统负载保护等多个维度保护服务的稳定性。此 Demo 仅演示了 使用 Sentinel 作为限流工具的使用,更多 Sentinel 相关的信息,请参考 [Sentinel 项目](https://github.com/alibaba/Sentinel)。
diff --git a/spring-cloud-alibaba-examples/sentinel-example/readme.md b/spring-cloud-alibaba-examples/sentinel-example/readme.md
index c9d61b25f..c1c3fb37b 100644
--- a/spring-cloud-alibaba-examples/sentinel-example/readme.md
+++ b/spring-cloud-alibaba-examples/sentinel-example/readme.md
@@ -165,42 +165,77 @@ To see the metrics, click **实时监控(Real-time Monitoring)** in the left-sid

-## Dubbo
+## DataSource
-[Dubbo](http://dubbo.apache.org/) is a high-performance, java based open source RPC framework.
+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 a module named [sentinel-dubbo-adapter](https://github.com/alibaba/Sentinel/tree/master/sentinel-adapter/sentinel-dubbo-adapter) to support dubbo.sentinel-starter integrates this feature by default.
+Sentinel starter integrated 4 DataSources provided by Sentinel. It will be register into Spring Context if you write some configs in `application.properties`.
-For example, a service named FooService, see the code below:
+If you want to define FileRefreshableDataSource:
- package org.springframework.cloud.alibaba.cloud.examples.dubbo.FooService;
- public interface FooService {
- String hello(String name);
- }
+ spring.cloud.sentinel.datasource.type=file
+ spring.cloud.sentinel.datasource.recommendRefreshMs=2000
+ spring.cloud.sentinel.datasource.bufSize=2048
+ spring.cloud.sentinel.datasource.charset=utf-8
+ spring.cloud.sentinel.datasource.configParser=myParser
+ spring.cloud.sentinel.datasource.file=/Users/you/rule.json
+
+then use `@SentinelDataSource` to annotate DataSource:
+
+ @SentinelDataSource("spring.cloud.sentinel.datasource")
+ private DataSource dataSource;
+
+The value() of `@SentinelDataSource` is not required, it means the prefix of configuration. Default value is `spring.cloud.sentinel.datasource`.
-The resource name of this service is `org.springframework.cloud.alibaba.cloud.examples.dubbo.FooService:hello(java.lang.String)` .
+spring.cloud.sentinel.datasource.type means the type of DataSource.
-You should handle SentinelRpcException if rpc invocation was be limited on Consumer side:
+spring.cloud.sentinel.datasource.recommendRefreshMs means the recommendRefreshMs property of specified DataSource.
- FooService service = applicationContext.getBean(FooService.class);
-
- for (int i = 0; i < 15; i++) {
- try {
- String message = service.hello("Jim");
- } catch (SentinelRpcException ex) {
- System.out.println("Blocked");
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
+spring.cloud.sentinel.datasource.configParser means the name of spring bean that type is ConfigParser. If the bean is not exists, will throw exception.
+
+Now datasource type support 4 categories: file, nacos, zk, apollo.
-It will throw RpcException on Consumer side if it was be limited on Provider side, because Provider side throw SentinelRpcException in this scene.
+### User-defined DataSource
-### Dubbo Start Application
+User-defined DataSource need 2 steps.
-You can startup ConsumerApplication after ServiceApplication startup.
+1. Define DataSource
+
+ public class CustomDataSource implements DataSource {
+ private String fieldA;
+ private String fieldB;
+ ...
+ }
+
+2. Assemble DataSource. There are 2 ways to do this.
+
+ * Construct DataSource directly
+
+ @Bean
+ public CustomDataSource customDataSource() {
+ CustomDataSource customDataSource = new CustomDataSource();
+ customDataSource.setFieldA("valueA");
+ customDataSource.setFieldB("valueB");
+ ...
+ return customDataSource;
+ }
-ConsumerApplication init flow control rules after startup, so you will find some invocations have been blocked in console.
+ * define DataSource metadata in `classpath:/META-INF/sentinel-datasource.properties`
+
+ custom = yourpackage.CustomDataSource
+
+ define configuration in `application.properties`
+
+ spring.cloud.sentinel.datasource.type = custom
+ spring.cloud.sentinel.datasource.fieldA = valueA
+ spring.cloud.sentinel.datasource.fieldB = valueB
+
+Note: The AbstractDataSource of Sentinel need a ConfigParser as a constructor param and the subclass of AbstractDataSource was construct by multi-param constructor.
+Now All DataSources in starter was construct by FactoryBean. If you want to do it in this way, you should register FactoryBean by SentinelDataSourceRegistry.
+
+ SentinelDataSourceRegistry.registerFactoryBean("custeom", CustomDataSourceFactoryBean.class);
+
+It is no need to using SentinelDataSourceRegistry to register FactoryBean if your User-defined DataSource can inject fields.
## More
For more information about Sentinel, see [Sentinel Project](https://github.com/alibaba/Sentinel).
diff --git a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/JsonFlowRuleListParser.java b/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/JsonFlowRuleListParser.java
new file mode 100644
index 000000000..255eb7892
--- /dev/null
+++ b/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/JsonFlowRuleListParser.java
@@ -0,0 +1,18 @@
+package org.springframework.cloud.alibaba.cloud.examples;
+
+import java.util.List;
+
+import com.alibaba.csp.sentinel.datasource.ConfigParser;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.TypeReference;
+
+/**
+ * @author fangjian
+ */
+public class JsonFlowRuleListParser implements ConfigParser> {
+ @Override
+ public List parse(String source) {
+ return JSON.parseObject(source, new TypeReference>() {});
+ }
+}
diff --git a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ServiceApplication.java b/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ServiceApplication.java
index 9d1696a94..c9df5fc78 100644
--- a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ServiceApplication.java
+++ b/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ServiceApplication.java
@@ -6,22 +6,29 @@ import org.springframework.cloud.alibaba.sentinel.annotation.SentinelProtect;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
+import com.alibaba.csp.sentinel.datasource.ConfigParser;
+
/**
* @author xiaojing
*/
@SpringBootApplication
public class ServiceApplication {
- @Bean
- @SentinelProtect(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)
- public RestTemplate restTemplate() {
- return new RestTemplate();
- }
+ @Bean
+ @SentinelProtect(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)
+ public RestTemplate restTemplate() {
+ return new RestTemplate();
+ }
- @Bean
- public RestTemplate restTemplate2() {
- return new RestTemplate();
- }
+ @Bean
+ public RestTemplate restTemplate2() {
+ return new RestTemplate();
+ }
+
+ @Bean
+ public ConfigParser myParser() {
+ return new JsonFlowRuleListParser();
+ }
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
diff --git a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/DubboProviderRunner.java b/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/DubboProviderRunner.java
deleted file mode 100644
index 4c683cddf..000000000
--- a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/DubboProviderRunner.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.springframework.cloud.alibaba.cloud.examples.dubbo;
-
-import org.springframework.boot.Banner;
-import org.springframework.boot.CommandLineRunner;
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.cloud.alibaba.cloud.examples.dubbo.provider.ProviderApplication;
-import org.springframework.stereotype.Component;
-
-/**
- * @author fangjian
- */
-@Component
-public class DubboProviderRunner implements CommandLineRunner {
-
- @Override
- public void run(String... args) throws Exception {
- SpringApplicationBuilder providerBuilder = new SpringApplicationBuilder()
- .bannerMode(Banner.Mode.OFF).registerShutdownHook(false)
- .logStartupInfo(false).web(false);
- providerBuilder.sources(ProviderApplication.class).run(args);
- }
-
-}
diff --git a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/FooService.java b/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/FooService.java
deleted file mode 100644
index d44b5c996..000000000
--- a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/FooService.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.springframework.cloud.alibaba.cloud.examples.dubbo;
-
-/**
- * @author fangjian
- */
-public interface FooService {
-
- String hello(String name);
-
-}
diff --git a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/consumer/ConsumerApplication.java b/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/consumer/ConsumerApplication.java
deleted file mode 100644
index 05e3d4b2d..000000000
--- a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/consumer/ConsumerApplication.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.springframework.cloud.alibaba.cloud.examples.dubbo.consumer;
-
-import java.util.Collections;
-
-import org.springframework.boot.Banner;
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Bean;
-
-import com.alibaba.csp.sentinel.slots.block.RuleConstant;
-import com.alibaba.csp.sentinel.slots.block.SentinelRpcException;
-import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
-import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
-import com.alibaba.dubbo.config.ApplicationConfig;
-import com.alibaba.dubbo.config.ConsumerConfig;
-import com.alibaba.dubbo.config.RegistryConfig;
-import com.alibaba.dubbo.config.spring.context.annotation.DubboComponentScan;
-
-/**
- * @author fangjian
- */
-@DubboComponentScan("org.springframework.cloud.alibaba.cloud.examples.dubbo.provider")
-public class ConsumerApplication {
-
- @Bean
- public ApplicationConfig applicationConfig() {
- ApplicationConfig applicationConfig = new ApplicationConfig();
- applicationConfig.setName("demo-consumer");
- return applicationConfig;
- }
-
- @Bean
- public RegistryConfig registryConfig() {
- RegistryConfig registryConfig = new RegistryConfig();
- registryConfig.setAddress("multicast://224.5.6.7:1234");
- return registryConfig;
- }
-
- @Bean
- public ConsumerConfig consumerConfig() {
- ConsumerConfig consumerConfig = new ConsumerConfig();
- return consumerConfig;
- }
-
- @Bean
- public FooServiceConsumer annotationDemoServiceConsumer() {
- return new FooServiceConsumer();
- }
-
- public static void main(String[] args) {
-
- SpringApplicationBuilder consumerBuilder = new SpringApplicationBuilder()
- .bannerMode(Banner.Mode.OFF).registerShutdownHook(false)
- .logStartupInfo(false).web(false);
- ApplicationContext applicationContext = consumerBuilder
- .sources(ConsumerApplication.class).run(args);
-
- FlowRule flowRule = new FlowRule();
- flowRule.setResource(
- "org.springframework.cloud.alibaba.cloud.examples.dubbo.FooService:hello(java.lang.String)");
- flowRule.setCount(10);
- flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
- flowRule.setLimitApp("default");
- FlowRuleManager.loadRules(Collections.singletonList(flowRule));
-
- FooServiceConsumer service = applicationContext.getBean(FooServiceConsumer.class);
-
- for (int i = 0; i < 15; i++) {
- try {
- String message = service.hello("Jim");
- System.out.println((i + 1) + " -> Success: " + message);
- }
- catch (SentinelRpcException ex) {
- System.out.println("Blocked");
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- }
-
-}
diff --git a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/consumer/FooServiceConsumer.java b/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/consumer/FooServiceConsumer.java
deleted file mode 100644
index 2fe62bf5a..000000000
--- a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/consumer/FooServiceConsumer.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.springframework.cloud.alibaba.cloud.examples.dubbo.consumer;
-
-import org.springframework.cloud.alibaba.cloud.examples.dubbo.FooService;
-
-import com.alibaba.dubbo.config.annotation.Reference;
-
-/**
- * @author fangjian
- */
-public class FooServiceConsumer {
-
- @Reference(url = "dubbo://127.0.0.1:25758", timeout = 3000)
- private FooService fooService;
-
- public String hello(String name) {
- return fooService.hello(name);
- }
-
-}
diff --git a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/provider/FooServiceImpl.java b/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/provider/FooServiceImpl.java
deleted file mode 100644
index bb9e81d66..000000000
--- a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/provider/FooServiceImpl.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.springframework.cloud.alibaba.cloud.examples.dubbo.provider;
-
-import org.springframework.cloud.alibaba.cloud.examples.dubbo.FooService;
-
-import com.alibaba.dubbo.config.annotation.Service;
-
-/**
- * @author fangjian
- */
-@Service
-public class FooServiceImpl implements FooService {
-
- @Override
- public String hello(String name) {
- return "hello, " + name;
- }
-}
diff --git a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/provider/ProviderApplication.java b/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/provider/ProviderApplication.java
deleted file mode 100644
index 6f793bb6e..000000000
--- a/spring-cloud-alibaba-examples/sentinel-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/dubbo/provider/ProviderApplication.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.springframework.cloud.alibaba.cloud.examples.dubbo.provider;
-
-import org.springframework.context.annotation.Bean;
-
-import com.alibaba.dubbo.config.ApplicationConfig;
-import com.alibaba.dubbo.config.ProtocolConfig;
-import com.alibaba.dubbo.config.RegistryConfig;
-import com.alibaba.dubbo.config.spring.context.annotation.DubboComponentScan;
-
-/**
- * @author fangjian
- */
-@DubboComponentScan("org.springframework.cloud.alibaba.cloud.examples.dubbo.provider")
-public class ProviderApplication {
-
- @Bean
- public ApplicationConfig applicationConfig() {
- ApplicationConfig applicationConfig = new ApplicationConfig();
- applicationConfig.setName("demo-provider");
- return applicationConfig;
- }
-
- @Bean
- public RegistryConfig registryConfig() {
- RegistryConfig registryConfig = new RegistryConfig();
- registryConfig.setAddress("multicast://224.5.6.7:1234");
- return registryConfig;
- }
-
- @Bean
- public ProtocolConfig protocolConfig() {
- ProtocolConfig protocolConfig = new ProtocolConfig();
- protocolConfig.setName("dubbo");
- protocolConfig.setPort(25758);
- return protocolConfig;
- }
-
-}
diff --git a/spring-cloud-alibaba-examples/sentinel-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/sentinel-example/src/main/resources/application.properties
index 252f0fdda..f8fa03ee6 100644
--- a/spring-cloud-alibaba-examples/sentinel-example/src/main/resources/application.properties
+++ b/spring-cloud-alibaba-examples/sentinel-example/src/main/resources/application.properties
@@ -2,4 +2,13 @@ spring.application.name=sentinel-example
server.port=18083
management.security.enabled=false
spring.cloud.sentinel.port=8721
-spring.cloud.sentinel.dashboard=localhost:8080
\ No newline at end of file
+spring.cloud.sentinel.dashboard=localhost:8080
+
+
+
+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.file=/Users/you/rule.json
\ No newline at end of file
diff --git a/spring-cloud-alibaba-sentinel/pom.xml b/spring-cloud-alibaba-sentinel/pom.xml
index cea895a76..31dd8e7b2 100644
--- a/spring-cloud-alibaba-sentinel/pom.xml
+++ b/spring-cloud-alibaba-sentinel/pom.xml
@@ -25,6 +25,29 @@
sentinel-transport-simple-http
+
+ com.alibaba.csp
+ sentinel-datasource-extension
+
+
+
+ com.alibaba.csp
+ sentinel-datasource-nacos
+ true
+
+
+
+ com.alibaba.csp
+ sentinel-datasource-zookeeper
+ true
+
+
+
+ com.alibaba.csp
+ sentinel-datasource-apollo
+ true
+
+
com.alibaba.csp
sentinel-annotation-aspectj
diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelEntry.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java
similarity index 53%
rename from spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelEntry.java
rename to spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java
index fdc4f3bf6..8f0318e39 100644
--- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelEntry.java
+++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java
@@ -14,41 +14,20 @@
* limitations under the License.
*/
-package org.springframework.cloud.alibaba.sentinel.custom;
-
-import com.alibaba.csp.sentinel.Entry;
+package org.springframework.cloud.alibaba.sentinel;
/**
- * @author xiaojing
+ * @author fangjian
*/
-public class SentinelEntry {
-
- private String key;
- private String handler;
-
- private Entry entry;
-
- public String getKey() {
- return key;
- }
+public interface SentinelConstants {
- public void setKey(String key) {
- this.key = key;
- }
+ String PROPERTY_PREFIX = "spring.cloud.sentinel";
- public String getHandler() {
- return handler;
- }
+ String PROPERTY_ITEM_SEPARATOR = ".";
- public void setHandler(String handler) {
- this.handler = handler;
- }
+ String PROPERTY_DATASOURCE_NAME = "datasource";
- public Entry getEntry() {
- return entry;
- }
+ String PROPERTY_DATASOURCE_PREFIX = PROPERTY_PREFIX + PROPERTY_ITEM_SEPARATOR
+ + PROPERTY_DATASOURCE_NAME;
- public void setEntry(Entry entry) {
- this.entry = entry;
- }
}
diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelProperties.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelProperties.java
index 283ea0705..eb1f2be77 100644
--- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelProperties.java
+++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelProperties.java
@@ -26,7 +26,7 @@ import org.springframework.core.Ordered;
* @author xiaojing
* @author hengyunabc
*/
-@ConfigurationProperties(prefix = "spring.cloud.sentinel")
+@ConfigurationProperties(prefix = SentinelConstants.PROPERTY_PREFIX)
public class SentinelProperties {
/**
diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelWebAutoConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelWebAutoConfiguration.java
index 81528668d..d588e3372 100644
--- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelWebAutoConfiguration.java
+++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelWebAutoConfiguration.java
@@ -16,25 +16,22 @@
package org.springframework.cloud.alibaba.sentinel;
-import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import java.util.ArrayList;
import java.util.List;
-import com.alibaba.csp.sentinel.transport.config.TransportConfig;
+import javax.servlet.Filter;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.util.StringUtils;
-import javax.annotation.PostConstruct;
-import javax.servlet.Filter;
+import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
/**
* @author xiaojing
@@ -47,30 +44,10 @@ public class SentinelWebAutoConfiguration {
private static final Logger logger = LoggerFactory
.getLogger(SentinelWebAutoConfiguration.class);
- @Value("${project.name:${spring.application.name:}}")
- private String projectName;
-
@Autowired
private SentinelProperties properties;
- public static final String APP_NAME = "project.name";
-
- @PostConstruct
- private void init() {
- if (StringUtils.isEmpty(System.getProperty(APP_NAME))) {
- System.setProperty(APP_NAME, projectName);
- }
- if (StringUtils.isEmpty(System.getProperty(TransportConfig.SERVER_PORT))) {
- System.setProperty(TransportConfig.SERVER_PORT, properties.getPort());
- }
- if (StringUtils.isEmpty(System.getProperty(TransportConfig.CONSOLE_SERVER))) {
- System.setProperty(TransportConfig.CONSOLE_SERVER, properties.getDashboard());
- }
-
- }
-
@Bean
- @ConditionalOnWebApplication
public FilterRegistrationBean servletRequestListener() {
FilterRegistrationBean registration = new FilterRegistrationBean();
diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/annotation/SentinelDataSource.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/annotation/SentinelDataSource.java
new file mode 100644
index 000000000..73a8ee173
--- /dev/null
+++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/annotation/SentinelDataSource.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * 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 org.springframework.cloud.alibaba.sentinel.annotation;
+
+import java.lang.annotation.*;
+
+import org.springframework.core.annotation.AliasFor;
+
+/**
+ * An annotation to inject {@link com.alibaba.csp.sentinel.datasource.DataSource} instance
+ * into a Spring Bean. The Properties of DataSource bean get from config files with
+ * specific prefix.
+ *
+ * @author fangjian
+ * @see com.alibaba.csp.sentinel.datasource.DataSource
+ */
+@Target({ ElementType.FIELD })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SentinelDataSource {
+
+ @AliasFor("prefix")
+ String value() default "";
+
+ @AliasFor("value")
+ String prefix() default "";
+
+ String name() default ""; // spring bean name
+
+}
diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java
index c473d94b4..2191f6a32 100644
--- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java
+++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java
@@ -16,20 +16,52 @@
package org.springframework.cloud.alibaba.sentinel.custom;
+import com.alibaba.csp.sentinel.transport.config.TransportConfig;
+import com.alibaba.csp.sentinel.util.AppNameUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.alibaba.sentinel.SentinelProperties;
+import org.springframework.cloud.alibaba.sentinel.datasource.SentinelDataSourcePostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
+import javax.annotation.PostConstruct;
+
/**
* @author xiaojing
*/
@Configuration
+@ConditionalOnProperty(name = "spring.cloud.sentinel.enabled", matchIfMissing = true)
+@EnableConfigurationProperties(SentinelProperties.class)
public class SentinelAutoConfiguration {
+ @Value("${project.name:${spring.application.name:}}")
+ private String projectName;
+
+ @Autowired
+ private SentinelProperties properties;
+
+ @PostConstruct
+ private void init() {
+ if (StringUtils.isEmpty(System.getProperty(AppNameUtil.APP_NAME))) {
+ System.setProperty(AppNameUtil.APP_NAME, projectName);
+ }
+ if (StringUtils.isEmpty(System.getProperty(TransportConfig.SERVER_PORT))) {
+ System.setProperty(TransportConfig.SERVER_PORT, properties.getPort());
+ }
+ if (StringUtils.isEmpty(System.getProperty(TransportConfig.CONSOLE_SERVER))) {
+ System.setProperty(TransportConfig.CONSOLE_SERVER, properties.getDashboard());
+ }
+ }
+
@Bean
@ConditionalOnMissingBean
public SentinelResourceAspect sentinelResourceAspect() {
@@ -38,9 +70,15 @@ public class SentinelAutoConfiguration {
@Bean
@ConditionalOnMissingBean
- @ConditionalOnClass(value = RestTemplate.class)
+ @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
public SentinelBeanPostProcessor sentinelBeanPostProcessor() {
return new SentinelBeanPostProcessor();
}
+ @Bean
+ @ConditionalOnMissingBean
+ public SentinelDataSourcePostProcessor sentinelDataSourcePostProcessor() {
+ return new SentinelDataSourcePostProcessor();
+ }
+
}
diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelProtectInterceptor.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelProtectInterceptor.java
index e48616489..dc22262f4 100644
--- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelProtectInterceptor.java
+++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelProtectInterceptor.java
@@ -43,7 +43,7 @@ import com.alibaba.csp.sentinel.util.StringUtil;
*/
public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor {
- private static final Logger LOGGER = LoggerFactory
+ private static final Logger logger = LoggerFactory
.getLogger(SentinelProtectInterceptor.class);
private SentinelProtect sentinelProtect;
@@ -68,12 +68,12 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor
response = execution.execute(request, body);
}
catch (BlockException e) {
- LOGGER.error("RestTemplate block", e);
+ logger.error("RestTemplate block", e);
try {
handleBlockException(e);
}
catch (Exception ex) {
- LOGGER.error("sentinel handle BlockException error.", e);
+ logger.error("sentinel handle BlockException error.", e);
}
}
finally {
diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java
new file mode 100644
index 000000000..183477cb5
--- /dev/null
+++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * 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 org.springframework.cloud.alibaba.sentinel.datasource;
+
+import static org.springframework.core.io.support.ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.PropertiesLoaderUtils;
+import org.springframework.core.io.support.ResourcePatternResolver;
+import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
+
+import com.alibaba.csp.sentinel.datasource.DataSource;
+
+/**
+ * {@link DataSource} Loader
+ *
+ * @author fangjian
+ */
+public class DataSourceLoader {
+
+ private static final Logger logger = LoggerFactory.getLogger(DataSourceLoader.class);
+
+ private final static String PROPERTIES_RESOURCE_LOCATION = "META-INF/sentinel-datasource.properties";
+
+ private final static String ALL_PROPERTIES_RESOURCES_LOCATION = CLASSPATH_ALL_URL_PREFIX
+ + PROPERTIES_RESOURCE_LOCATION;
+
+ private final static ConcurrentMap> dataSourceClassesCache = new ConcurrentHashMap>(
+ 4);
+
+ static void loadAllDataSourceClassesCache() {
+ Map> dataSourceClassesMap = loadAllDataSourceClassesCache(
+ ALL_PROPERTIES_RESOURCES_LOCATION);
+
+ dataSourceClassesCache.putAll(dataSourceClassesMap);
+ }
+
+ static Map> loadAllDataSourceClassesCache(
+ String resourcesLocation) {
+
+ Map> dataSourcesMap = new HashMap>(
+ 4);
+
+ ClassLoader classLoader = DataSourceLoader.class.getClassLoader();
+
+ ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
+
+ try {
+
+ Resource[] resources = resolver.getResources(resourcesLocation);
+
+ for (Resource resource : resources) {
+ if (resource.exists()) {
+ Properties properties = PropertiesLoaderUtils
+ .loadProperties(resource);
+ for (Map.Entry
+
+ com.alibaba.csp
+ sentinel-datasource-nacos
+
+
+ com.alibaba.csp
+ sentinel-datasource-zookeeper
+
+
+ com.alibaba.csp
+ sentinel-datasource-apollo
+