Initial commit for Sentinel Dubbo Adapter
Signed-off-by: Eric Zhao <sczyh16@gmail.com>
diff --git a/.gitignore b/.gitignore
index a1c2a23..378800f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,23 +1,26 @@
-# Compiled class file
-*.class
+# IntelliJ project files
+.idea/
+*.iml
+out
+gen
-# Log file
-*.log
+# Maven
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+!/.mvn/wrapper/maven-wrapper.jar
-# BlueJ files
-*.ctxt
+# Eclipse
+.classpath
+.settings/
+.project
-# Mobile Tools for Java (J2ME)
-.mtj.tmp/
-
-# Package Files #
-*.jar
-*.war
-*.nar
-*.ear
-*.zip
-*.tar.gz
-*.rar
-
-# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
-hs_err_pid*
+# System related
+*.DS_Store
+Thumbs.db
diff --git a/README.md b/README.md
index 9b0be3d..d112457 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,53 @@
-# dubbo-sentinel-support
\ No newline at end of file
+# Sentinel Dubbo Adapter
+
+Sentinel Dubbo Adapter provides service consumer filter and provider filter
+for [Dubbo](http://dubbo.io/) services.
+
+To use Sentinel Dubbo Adapter, you can simply add the following dependency to your `pom.xml`:
+
+```xml
+<dependency>
+ <groupId>com.alibaba.csp</groupId>
+ <artifactId>sentinel-dubbo-adapter</artifactId>
+ <version>x.y.z</version>
+</dependency>
+```
+
+The Sentinel filters are **enabled by default**. Once you add the dependency,
+the Dubbo services and methods will become protected resources in Sentinel,
+which can leverage Sentinel's flow control and guard ability when rules are configured.
+Demos can be found in [sentinel-demo-dubbo](https://github.com/alibaba/Sentinel/tree/master/sentinel-demo/sentinel-demo-dubbo).
+
+If you don't want the filters enabled, you can manually disable them. For example:
+
+```xml
+<dubbo:consumer filter="-sentinel.dubbo.consumer.filter"/>
+
+<dubbo:provider filter="-sentinel.dubbo.provider.filter"/>
+```
+
+For more details of Dubbo filter, see [here](https://dubbo.incubator.apache.org/#/docs/dev/impls/filter.md?lang=en-us).
+
+## Dubbo resources
+
+The resource for Dubbo services has two granularities: service interface and service method.
+
+- Service interface:resourceName format is `interfaceName`,e.g. `com.alibaba.csp.sentinel.demo.dubbo.FooService`
+- Service method:resourceName format is `interfaceName:methodSignature`,e.g. `com.alibaba.csp.sentinel.demo.dubbo.FooService:sayHello(java.lang.String)`
+
+## Flow control based on caller
+
+In many circumstances, it's also significant to control traffic flow based on the **caller**.
+For example, assuming that there are two services A and B, both of them initiate remote call requests to the service provider.
+If we want to limit the calls from service B only, we can set the `limitApp` of flow rule as the identifier of service B (e.g. service name).
+
+Sentinel Dubbo Adapter will automatically resolve the Dubbo consumer's *application name* as the caller's name (`origin`),
+and will bring the caller's name when doing resource protection.
+If `limitApp` of flow rules is not configured (`default`), flow control will take effects on all callers.
+If `limitApp` of a flow rule is configured with a caller, then the corresponding flow rule will only take effect on the specific caller.
+
+> Note: Dubbo consumer does not provide its Dubbo application name when doing RPC,
+so developers should manually put the application name into *attachment* at consumer side,
+then extract it at provider side. Sentinel Dubbo Adapter has implemented a filter (`DubboAppContextFilter`)
+where consumer can carry application name information to provider automatically.
+If the consumer does not use Sentinel Dubbo Adapter but requires flow control based on caller, developers can manually put the application name into attachment with the key `dubboApplication`.
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..a7ed335
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>com.alibaba.csp</groupId>
+ <artifactId>sentinel-adapter</artifactId>
+ <version>0.1.0</version>
+ </parent>
+ <artifactId>sentinel-dubbo-adapter</artifactId>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.alibaba.csp</groupId>
+ <artifactId>sentinel-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>dubbo</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>fastjson</artifactId>
+ <version>1.2.47</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+
+</project>
\ No newline at end of file
diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/AbstractDubboFilter.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/AbstractDubboFilter.java
new file mode 100755
index 0000000..2400b3c
--- /dev/null
+++ b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/AbstractDubboFilter.java
@@ -0,0 +1,29 @@
+package com.alibaba.csp.sentinel.adapter.dubbo;
+
+import com.alibaba.dubbo.rpc.Filter;
+import com.alibaba.dubbo.rpc.Invocation;
+import com.alibaba.dubbo.rpc.Invoker;
+
+/**
+ * @author leyou
+ */
+abstract class AbstractDubboFilter implements Filter {
+
+ protected String getResourceName(Invoker<?> invoker, Invocation invocation) {
+ StringBuilder buf = new StringBuilder(64);
+ buf.append(invoker.getInterface().getName())
+ .append(":")
+ .append(invocation.getMethodName())
+ .append("(");
+ boolean isFirst = true;
+ for (Class<?> clazz : invocation.getParameterTypes()) {
+ if (!isFirst) {
+ buf.append(",");
+ }
+ buf.append(clazz.getName());
+ isFirst = false;
+ }
+ buf.append(")");
+ return buf.toString();
+ }
+}
diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboAppContextFilter.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboAppContextFilter.java
new file mode 100644
index 0000000..36835cc
--- /dev/null
+++ b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboAppContextFilter.java
@@ -0,0 +1,28 @@
+package com.alibaba.csp.sentinel.adapter.dubbo;
+
+import com.alibaba.dubbo.common.Constants;
+import com.alibaba.dubbo.common.extension.Activate;
+import com.alibaba.dubbo.rpc.Filter;
+import com.alibaba.dubbo.rpc.Invocation;
+import com.alibaba.dubbo.rpc.Invoker;
+import com.alibaba.dubbo.rpc.Result;
+import com.alibaba.dubbo.rpc.RpcContext;
+import com.alibaba.dubbo.rpc.RpcException;
+
+/**
+ * Puts current consumer's application name in the attachment of each invocation.
+ *
+ * @author Eric Zhao
+ */
+@Activate(group = "consumer")
+public class DubboAppContextFilter implements Filter {
+
+ @Override
+ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
+ String application = invoker.getUrl().getParameter(Constants.APPLICATION_KEY);
+ if (application != null) {
+ RpcContext.getContext().setAttachment(DubboUtils.DUBBO_APPLICATION_KEY, application);
+ }
+ return invoker.invoke(invocation);
+ }
+}
diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java
new file mode 100644
index 0000000..73fd51b
--- /dev/null
+++ b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java
@@ -0,0 +1,20 @@
+package com.alibaba.csp.sentinel.adapter.dubbo;
+
+import com.alibaba.dubbo.rpc.Invocation;
+
+/**
+ * @author Eric Zhao
+ */
+public final class DubboUtils {
+
+ public static final String DUBBO_APPLICATION_KEY = "dubboApplication";
+
+ public static String getApplication(Invocation invocation, String defaultValue) {
+ if (invocation == null || invocation.getAttachments() == null) {
+ throw new IllegalArgumentException("Bad invocation instance");
+ }
+ return invocation.getAttachment(DUBBO_APPLICATION_KEY, defaultValue);
+ }
+
+ private DubboUtils() {}
+}
diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java
new file mode 100755
index 0000000..2f79b04
--- /dev/null
+++ b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java
@@ -0,0 +1,55 @@
+package com.alibaba.csp.sentinel.adapter.dubbo;
+
+import com.alibaba.csp.sentinel.Entry;
+import com.alibaba.csp.sentinel.EntryType;
+import com.alibaba.csp.sentinel.SphU;
+import com.alibaba.csp.sentinel.Tracer;
+import com.alibaba.csp.sentinel.context.ContextUtil;
+import com.alibaba.csp.sentinel.slots.block.BlockException;
+import com.alibaba.csp.sentinel.slots.block.SentinelRpcException;
+import com.alibaba.dubbo.common.extension.Activate;
+import com.alibaba.dubbo.rpc.Filter;
+import com.alibaba.dubbo.rpc.Invocation;
+import com.alibaba.dubbo.rpc.Invoker;
+import com.alibaba.dubbo.rpc.Result;
+import com.alibaba.dubbo.rpc.RpcException;
+
+/**
+ * <p>Dubbo service consumer filter for Sentinel. Auto activated by default.</p>
+ *
+ * If you want to disable the consumer filter, you can configure:
+ * <pre>
+ * <dubbo:consumer filter="-sentinel.dubbo.consumer.filter"/>
+ * </pre>
+ *
+ * @author leyou
+ */
+@Activate(group = "consumer")
+public class SentinelDubboConsumerFilter extends AbstractDubboFilter implements Filter {
+
+ @Override
+ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
+ Entry interfaceEntry = null;
+ Entry methodEntry = null;
+ try {
+ String resourceName = getResourceName(invoker, invocation);
+ ContextUtil.enter(resourceName);
+ interfaceEntry = SphU.entry(invoker.getInterface().getName(), EntryType.OUT);
+ methodEntry = SphU.entry(resourceName, EntryType.OUT);
+ return invoker.invoke(invocation);
+ } catch (BlockException e) {
+ throw new SentinelRpcException(e);
+ } catch (RpcException e) {
+ Tracer.trace(e);
+ throw e;
+ } finally {
+ if (methodEntry != null) {
+ methodEntry.exit();
+ }
+ if (interfaceEntry != null) {
+ interfaceEntry.exit();
+ }
+ ContextUtil.exit();
+ }
+ }
+}
diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java
new file mode 100755
index 0000000..8c3951f
--- /dev/null
+++ b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java
@@ -0,0 +1,60 @@
+package com.alibaba.csp.sentinel.adapter.dubbo;
+
+import com.alibaba.csp.sentinel.Entry;
+import com.alibaba.csp.sentinel.EntryType;
+import com.alibaba.csp.sentinel.SphU;
+import com.alibaba.csp.sentinel.Tracer;
+import com.alibaba.csp.sentinel.context.ContextUtil;
+import com.alibaba.csp.sentinel.slots.block.BlockException;
+import com.alibaba.csp.sentinel.slots.block.SentinelRpcException;
+import com.alibaba.dubbo.common.extension.Activate;
+import com.alibaba.dubbo.rpc.Filter;
+import com.alibaba.dubbo.rpc.Invocation;
+import com.alibaba.dubbo.rpc.Invoker;
+import com.alibaba.dubbo.rpc.Result;
+import com.alibaba.dubbo.rpc.RpcException;
+
+/**
+ * <p>Dubbo service provider filter for Sentinel. Auto activated by default.</p>
+ *
+ * If you want to disable the provider filter, you can configure:
+ * <pre>
+ * <dubbo:provider filter="-sentinel.dubbo.provider.filter"/>
+ * </pre>
+ *
+ * @author leyou
+ */
+@Activate(group = "provider")
+public class SentinelDubboProviderFilter extends AbstractDubboFilter implements Filter {
+
+ @Override
+ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
+ // Get origin caller.
+ String application = DubboUtils.getApplication(invocation, "");
+
+ Entry interfaceEntry = null;
+ Entry methodEntry = null;
+ try {
+ String resourceName = getResourceName(invoker, invocation);
+ String interfaceName = invoker.getInterface().getName();
+ ContextUtil.enter(resourceName, application);
+ interfaceEntry = SphU.entry(interfaceName, EntryType.IN);
+ methodEntry = SphU.entry(resourceName, EntryType.IN, 1, invocation.getArguments());
+
+ return invoker.invoke(invocation);
+ } catch (BlockException e) {
+ throw new SentinelRpcException(e);
+ } catch (RpcException e) {
+ Tracer.trace(e);
+ throw e;
+ } finally {
+ if (methodEntry != null) {
+ methodEntry.exit(1, invocation.getArguments());
+ }
+ if (interfaceEntry != null) {
+ interfaceEntry.exit();
+ }
+ ContextUtil.exit();
+ }
+ }
+}
diff --git a/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter b/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter
new file mode 100755
index 0000000..af7c961
--- /dev/null
+++ b/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter
@@ -0,0 +1,3 @@
+sentinel.dubbo.provider.filter=com.alibaba.csp.sentinel.adapter.dubbo.SentinelDubboProviderFilter
+sentinel.dubbo.consumer.filter=com.alibaba.csp.sentinel.adapter.dubbo.SentinelDubboConsumerFilter
+dubbo.application.context.name.filter=com.alibaba.csp.sentinel.adapter.dubbo.DubboAppContextFilter
\ No newline at end of file
diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DemoService.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DemoService.java
new file mode 100755
index 0000000..8ccc4a0
--- /dev/null
+++ b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DemoService.java
@@ -0,0 +1,8 @@
+package com.alibaba.csp.sentinel.adapter.dubbo;
+
+/**
+ * @author leyou
+ */
+public interface DemoService {
+ String sayHello(String name, int n);
+}
diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboConsumerTest.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboConsumerTest.java
new file mode 100755
index 0000000..4ba0a4d
--- /dev/null
+++ b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboConsumerTest.java
@@ -0,0 +1,74 @@
+package com.alibaba.csp.sentinel.adapter.dubbo;
+
+import java.util.Arrays;
+
+import com.alibaba.csp.sentinel.node.ClusterNode;
+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.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * 运行该用例的时候需要加入JVM参数:-Djava.net.preferIPv4Stack=true,
+ * 否则可能会抛出{@code java.lang.IllegalStateException: Can't assign requested address}
+ *
+ * @author leyou
+ */
+public class DubboConsumerTest {
+ private final String resource = "com.alibaba.csp.sentinel.adapter.dubbo.DemoService:sayHello(java.lang.String,int)";
+ private final String interfaceResource = "com.alibaba.csp.sentinel.adapter.dubbo.DemoService";
+ private ClassPathXmlApplicationContext context;
+
+ @Before
+ public void init() {
+ context = new ClassPathXmlApplicationContext(
+ new String[] {"spring-dubbo-consumer-filter.xml"});
+ context.start();
+ }
+
+ @Test
+ public void testConsumerFilter() throws Exception {
+ DemoService demoService = (DemoService)context.getBean("demoService");
+ String result = demoService.sayHello("Test dubbo consumer filter", 2);
+ System.out.println("result=" + result);
+ ClusterNode node = ClusterBuilderSlot.getClusterNode(resource);
+ Assert.assertNotNull(node);
+ }
+
+ @Test(expected = SentinelRpcException.class)
+ public void testConsumerBlock() throws Exception {
+ FlowRule flowRule = new FlowRule();
+ flowRule.setResource(resource);
+ flowRule.setCount(10);
+ flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
+ flowRule.setLimitApp("default");
+ FlowRuleManager.loadRules(Arrays.asList(flowRule));
+
+ DemoService demoService = (DemoService)context.getBean("demoService");
+ for (int i = 0; i < 100; i++) {
+ demoService.sayHello("Test dubbo consumer filter", 2);
+ }
+ }
+
+ @Test(expected = SentinelRpcException.class)
+ public void testConsumerBlock2() throws Exception {
+ FlowRule flowRule = new FlowRule();
+ flowRule.setResource(interfaceResource);
+ flowRule.setCount(10);
+ flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
+ flowRule.setLimitApp("default");
+ FlowRuleManager.loadRules(Arrays.asList(flowRule));
+
+ DemoService demoService = (DemoService)context.getBean("demoService");
+ for (int i = 0; i < 100; i++) {
+ demoService.sayHello("Test dubbo consumer filter", 2);
+ }
+ }
+
+}
diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboProviderTest.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboProviderTest.java
new file mode 100755
index 0000000..8c4657e
--- /dev/null
+++ b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboProviderTest.java
@@ -0,0 +1,32 @@
+package com.alibaba.csp.sentinel.adapter.dubbo;
+
+import com.alibaba.csp.sentinel.node.ClusterNode;
+import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * 运行该用例的时候需要加入JVM参数:-Djava.net.preferIPv4Stack=true,
+ * 否则可能会抛出{@code java.lang.IllegalStateException: Can't assign requested address}
+ *
+ * @author leyou
+ */
+public class DubboProviderTest {
+
+ private final String resource = "com.alibaba.csp.sentinel.adapter.dubbo.DemoService:sayHello(java.lang.String,int)";
+
+ @Test
+ public void testProviderFilter() throws Exception {
+ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
+ new String[] {"spring-dubbo-provider-filter.xml"});
+ context.start();
+ DemoService demoService = (DemoService)context.getBean("demoService");
+ String result = demoService.sayHello("Test dubbo provider filter", 1);
+ System.out.println("result=" + result);
+ ClusterNode node = ClusterBuilderSlot.getClusterNode(resource);
+ Thread.sleep(1000 * 60 * 100);
+ Assert.assertNotNull(node);
+ }
+}
diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/provider/DemoServiceImpl.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/provider/DemoServiceImpl.java
new file mode 100755
index 0000000..db566e7
--- /dev/null
+++ b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/provider/DemoServiceImpl.java
@@ -0,0 +1,12 @@
+package com.alibaba.csp.sentinel.adapter.dubbo.provider;
+
+import com.alibaba.csp.sentinel.adapter.dubbo.DemoService;
+
+/**
+ * @author leyou
+ */
+public class DemoServiceImpl implements DemoService {
+ public String sayHello(String name, int n) {
+ return "Hello " + name + ", " + n;
+ }
+}
diff --git a/src/test/resources/spring-dubbo-consumer-filter.xml b/src/test/resources/spring-dubbo-consumer-filter.xml
new file mode 100755
index 0000000..ae0a89d
--- /dev/null
+++ b/src/test/resources/spring-dubbo-consumer-filter.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://code.alibabatech.com/schema/dubbo
+ http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
+
+ <dubbo:application name="demo-consumer"/>
+ <dubbo:registry address="multicast://224.5.6.7:1234"/>
+ <dubbo:protocol name="dubbo" port="20880"/>
+ <dubbo:service interface="com.alibaba.csp.sentinel.adapter.dubbo.DemoService" ref="demoServiceImp" />
+ <bean id="demoServiceImp" class="com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoServiceImpl"/>
+
+ <dubbo:reference id="demoService" interface="com.alibaba.csp.sentinel.adapter.dubbo.DemoService"/>
+
+ <dubbo:consumer filter="sentinel.dubbo.consumer.filter" />
+
+</beans>
\ No newline at end of file
diff --git a/src/test/resources/spring-dubbo-provider-filter.xml b/src/test/resources/spring-dubbo-provider-filter.xml
new file mode 100755
index 0000000..0990c39
--- /dev/null
+++ b/src/test/resources/spring-dubbo-provider-filter.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://code.alibabatech.com/schema/dubbo
+ http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
+
+ <dubbo:application name="demo-provider"/>
+ <dubbo:registry address="multicast://224.5.6.7:1234"/>
+ <dubbo:protocol name="dubbo" port="20880"/>
+ <dubbo:service interface="com.alibaba.csp.sentinel.adapter.dubbo.DemoService" ref="demoServiceImp" />
+ <bean id="demoServiceImp" class="com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoServiceImpl"/>
+
+ <dubbo:reference id="demoService" interface="com.alibaba.csp.sentinel.adapter.dubbo.DemoService"/>
+
+ <dubbo:provider filter="sentinel.dubbo.provider.filter" />
+
+</beans>
\ No newline at end of file