From 6719ceef65258aa691e0424967ac9b5865c9ee2b Mon Sep 17 00:00:00 2001
From: zhangxn <840267340@qq.com>
Date: Sat, 5 Dec 2020 13:56:36 +0800
Subject: [PATCH] Add Motan RPC adapter implementation (#1825)

---
 sentinel-adapter/pom.xml                      |  1 +
 .../sentinel-motan-adapter/pom.xml            | 50 ++++++++++
 .../sentinel/adapter/motan/MotanUtils.java    | 89 ++++++++++++++++++
 .../motan/SentinelMotanConsumerFilter.java    | 74 +++++++++++++++
 .../motan/SentinelMotanProviderFilter.java    | 80 ++++++++++++++++
 .../config/MotanAdapterGlobalConfig.java      | 94 +++++++++++++++++++
 .../motan/fallback/DefaultMotanFallback.java  | 38 ++++++++
 .../adapter/motan/fallback/MotanFallback.java | 37 ++++++++
 .../com.weibo.api.motan.filter.Filter         |  2 +
 sentinel-demo/pom.xml                         |  1 +
 sentinel-demo/sentinel-demo-motan/pom.xml     | 68 ++++++++++++++
 .../motan/SentinelMotanConsumerService.java   | 90 ++++++++++++++++++
 .../motan/SentinelMotanProviderService.java   | 72 ++++++++++++++
 .../demo/motan/service/MotanDemoService.java  | 25 +++++
 .../service/impl/MotanDemoServiceImpl.java    | 30 ++++++
 .../src/main/resources/sentinel.properties    |  1 +
 16 files changed, 752 insertions(+)
 create mode 100644 sentinel-adapter/sentinel-motan-adapter/pom.xml
 create mode 100644 sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/MotanUtils.java
 create mode 100644 sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/SentinelMotanConsumerFilter.java
 create mode 100644 sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/SentinelMotanProviderFilter.java
 create mode 100644 sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/config/MotanAdapterGlobalConfig.java
 create mode 100644 sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/fallback/DefaultMotanFallback.java
 create mode 100644 sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/fallback/MotanFallback.java
 create mode 100644 sentinel-adapter/sentinel-motan-adapter/src/main/resources/META-INF/services/com.weibo.api.motan.filter.Filter
 create mode 100644 sentinel-demo/sentinel-demo-motan/pom.xml
 create mode 100644 sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/SentinelMotanConsumerService.java
 create mode 100644 sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/SentinelMotanProviderService.java
 create mode 100644 sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/service/MotanDemoService.java
 create mode 100644 sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/service/impl/MotanDemoServiceImpl.java
 create mode 100644 sentinel-demo/sentinel-demo-motan/src/main/resources/sentinel.properties

diff --git a/sentinel-adapter/pom.xml b/sentinel-adapter/pom.xml
index 2b35586d..f153452e 100755
--- a/sentinel-adapter/pom.xml
+++ b/sentinel-adapter/pom.xml
@@ -31,6 +31,7 @@
         <module>sentinel-okhttp-adapter</module>
         <module>sentinel-jax-rs-adapter</module>
         <module>sentinel-quarkus-adapter</module>
+        <module>sentinel-motan-adapter</module>
     </modules>
 
     <dependencyManagement>
diff --git a/sentinel-adapter/sentinel-motan-adapter/pom.xml b/sentinel-adapter/sentinel-motan-adapter/pom.xml
new file mode 100644
index 00000000..6ccb1a3b
--- /dev/null
+++ b/sentinel-adapter/sentinel-motan-adapter/pom.xml
@@ -0,0 +1,50 @@
+<?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">
+    <parent>
+        <artifactId>sentinel-adapter</artifactId>
+        <groupId>com.alibaba.csp</groupId>
+        <version>1.8.1-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>sentinel-motan-adapter</artifactId>
+    <packaging>jar</packaging>
+
+    <properties>
+        <motan.version>1.1.8</motan.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba.csp</groupId>
+            <artifactId>sentinel-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.weibo</groupId>
+            <artifactId>motan-core</artifactId>
+            <version>${motan.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.weibo</groupId>
+            <artifactId>motan-transport-netty4</artifactId>
+            <version>${motan.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${maven.compiler.version}</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                    <encoding>${java.encoding}</encoding>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/MotanUtils.java b/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/MotanUtils.java
new file mode 100644
index 00000000..19967c24
--- /dev/null
+++ b/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/MotanUtils.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 1999-2020 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
+ *
+ *      https://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.adapter.motan;
+
+import com.alibaba.csp.sentinel.adapter.motan.config.MotanAdapterGlobalConfig;
+import com.alibaba.csp.sentinel.util.StringUtil;
+import com.weibo.api.motan.rpc.Caller;
+import com.weibo.api.motan.rpc.Request;
+import com.weibo.api.motan.util.ReflectUtil;
+
+/**
+ * @author zhangxn8
+ */
+public class MotanUtils {
+
+    private MotanUtils() {}
+
+    public static String getMethodResourceName(Caller<?> caller, Request request){
+        return getMethodResourceName(caller, request, false);
+    }
+
+    public static String getMethodResourceName(Caller<?> caller, Request request, Boolean useGroupAndVersion) {
+        StringBuilder buf = new StringBuilder(64);
+        String interfaceResource = useGroupAndVersion ? caller.getUrl().getPath(): caller.getInterface().getName();
+        buf.append(interfaceResource)
+                .append(":")
+                .append(request.getMethodName())
+                .append("(");
+        boolean isFirst = true;
+        try {
+            Class<?>[] classTypes = ReflectUtil.forNames(request.getParamtersDesc());
+            for (Class<?> clazz : classTypes) {
+                if (!isFirst) {
+                    buf.append(",");
+                }
+                buf.append(clazz.getName());
+                isFirst = false;
+            }
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        }
+        buf.append(")");
+        return buf.toString();
+    }
+
+    public static String getMethodResourceName(Caller<?> caller, Request request, String prefix) {
+        if (StringUtil.isNotBlank(prefix)) {
+            return new StringBuilder(64)
+                    .append(prefix)
+                    .append(getMethodResourceName(caller, request,MotanAdapterGlobalConfig.getMotanInterfaceGroupAndVersionEnabled()))
+                    .toString();
+        } else {
+            return getMethodResourceName(caller, request,MotanAdapterGlobalConfig.getMotanInterfaceGroupAndVersionEnabled());
+        }
+    }
+
+    public static String getInterfaceName(Caller<?> caller) {
+        return getInterfaceName(caller, false);
+    }
+
+    public static String getInterfaceName(Caller<?> caller, Boolean useGroupAndVersion) {
+        return useGroupAndVersion ? caller.getUrl().getApplication() : caller.getInterface().getName();
+    }
+
+    public static String getInterfaceName(Caller<?> caller, String prefix) {
+        if (StringUtil.isNotBlank(prefix)) {
+            return new StringBuilder(64)
+                    .append(prefix)
+                    .append(getInterfaceName(caller, MotanAdapterGlobalConfig.getMotanInterfaceGroupAndVersionEnabled()))
+                    .toString();
+        } else {
+            return getInterfaceName(caller, MotanAdapterGlobalConfig.getMotanInterfaceGroupAndVersionEnabled());
+        }
+    }
+
+}
diff --git a/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/SentinelMotanConsumerFilter.java b/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/SentinelMotanConsumerFilter.java
new file mode 100644
index 00000000..eda65b54
--- /dev/null
+++ b/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/SentinelMotanConsumerFilter.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 1999-2020 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
+ *
+ *      https://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.adapter.motan;
+
+import com.alibaba.csp.sentinel.*;
+import com.alibaba.csp.sentinel.adapter.motan.config.MotanAdapterGlobalConfig;
+import com.alibaba.csp.sentinel.log.RecordLog;
+import com.alibaba.csp.sentinel.slots.block.BlockException;
+import com.weibo.api.motan.common.MotanConstants;
+import com.weibo.api.motan.core.extension.Activation;
+import com.weibo.api.motan.core.extension.SpiMeta;
+import com.weibo.api.motan.exception.MotanAbstractException;
+import com.weibo.api.motan.filter.Filter;
+import com.weibo.api.motan.rpc.Caller;
+import com.weibo.api.motan.rpc.Request;
+import com.weibo.api.motan.rpc.Response;
+
+/**
+ * @author zhangxn8
+ */
+@Activation(key = MotanConstants.NODE_TYPE_REFERER)
+@SpiMeta(name = MotanAdapterGlobalConfig.SENTINEL_MOTAN_CONSUMER)
+public class SentinelMotanConsumerFilter implements Filter {
+
+    public SentinelMotanConsumerFilter(){
+        RecordLog.info("Sentinel motan consumer filter initialized");
+    }
+
+    @Override
+    public Response filter(Caller<?> caller, Request request) {
+        Entry interfaceEntry = null;
+        Entry methodEntry = null;
+        String prefix = MotanAdapterGlobalConfig.getMotanConsumerPrefix();
+        String interfaceResourceName = MotanUtils.getInterfaceName(caller, prefix);
+        String methodResourceName = MotanUtils.getMethodResourceName(caller, request, prefix);
+        try {
+            interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT);
+            methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT,
+                    request.getArguments());
+            Response result = caller.call(request);
+            if (result.getException() != null) {
+                Tracer.traceEntry(result.getException(), interfaceEntry);
+                Tracer.traceEntry(result.getException(), methodEntry);
+            }
+            return result;
+        } catch (BlockException e) {
+            return MotanAdapterGlobalConfig.getConsumerFallback().handle(caller, request, e);
+        } catch (MotanAbstractException e) {
+            Tracer.traceEntry(e, interfaceEntry);
+            Tracer.traceEntry(e, methodEntry);
+            throw e;
+        } finally {
+            if (methodEntry != null) {
+                methodEntry.exit(1, request.getArguments());
+            }
+            if (interfaceEntry != null) {
+                interfaceEntry.exit();
+            }
+        }
+    }
+}
diff --git a/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/SentinelMotanProviderFilter.java b/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/SentinelMotanProviderFilter.java
new file mode 100644
index 00000000..3ad777b1
--- /dev/null
+++ b/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/SentinelMotanProviderFilter.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 1999-2020 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
+ *
+ *      https://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.adapter.motan;
+
+import com.alibaba.csp.sentinel.*;
+import com.alibaba.csp.sentinel.adapter.motan.config.MotanAdapterGlobalConfig;
+import com.alibaba.csp.sentinel.context.ContextUtil;
+import com.alibaba.csp.sentinel.log.RecordLog;
+import com.alibaba.csp.sentinel.slots.block.BlockException;
+import com.weibo.api.motan.common.MotanConstants;
+import com.weibo.api.motan.core.extension.Activation;
+import com.weibo.api.motan.core.extension.SpiMeta;
+import com.weibo.api.motan.exception.MotanAbstractException;
+import com.weibo.api.motan.filter.Filter;
+import com.weibo.api.motan.rpc.Caller;
+import com.weibo.api.motan.rpc.Request;
+import com.weibo.api.motan.rpc.Response;
+import java.util.Map;
+
+/**
+ * @author zhangxn8
+ */
+@Activation(key = MotanConstants.NODE_TYPE_SERVICE)
+@SpiMeta(name = MotanAdapterGlobalConfig.SENTINEL_MOTAN_PROVIDER)
+public class SentinelMotanProviderFilter implements Filter {
+
+    public SentinelMotanProviderFilter(){
+        RecordLog.info("Sentinel motan provider filter initialized");
+    }
+
+    @Override
+    public Response filter(Caller<?> caller, Request request) {
+        Entry interfaceEntry = null;
+        Entry methodEntry = null;
+        Map<String, String> attachment = request.getAttachments();
+        String origin = attachment.getOrDefault(MotanAdapterGlobalConfig.APPLICATION, MotanAdapterGlobalConfig.MOTAN);
+        String prefix = MotanAdapterGlobalConfig.getMotanProviderPrefix();
+        String interfaceResourceName = MotanUtils.getInterfaceName(caller, prefix);
+        String methodResourceName = MotanUtils.getMethodResourceName(caller, request, prefix);
+        try {
+            ContextUtil.enter(methodResourceName, origin);
+            interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN);
+            methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN,
+                    request.getArguments());
+            Response result = caller.call(request);
+            if (result.getException() != null) {
+                Tracer.traceEntry(result.getException(), interfaceEntry);
+                Tracer.traceEntry(result.getException(), methodEntry);
+            }
+            return result;
+        } catch (BlockException e) {
+            return MotanAdapterGlobalConfig.getProviderFallback().handle(caller, request, e);
+        } catch (MotanAbstractException e) {
+            Tracer.traceEntry(e, interfaceEntry);
+            Tracer.traceEntry(e, methodEntry);
+            throw e;
+        } finally {
+            if (methodEntry != null) {
+                methodEntry.exit(1, request.getArguments());
+            }
+            if (interfaceEntry != null) {
+                interfaceEntry.exit();
+            }
+            ContextUtil.exit();
+        }
+    }
+}
diff --git a/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/config/MotanAdapterGlobalConfig.java b/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/config/MotanAdapterGlobalConfig.java
new file mode 100644
index 00000000..a4e34ca0
--- /dev/null
+++ b/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/config/MotanAdapterGlobalConfig.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 1999-2020 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
+ *
+ *      https://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.adapter.motan.config;
+
+import com.alibaba.csp.sentinel.adapter.motan.fallback.DefaultMotanFallback;
+import com.alibaba.csp.sentinel.adapter.motan.fallback.MotanFallback;
+import com.alibaba.csp.sentinel.config.SentinelConfig;
+import com.alibaba.csp.sentinel.util.AssertUtil;
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+/**
+ * @author zhangxn8
+ */
+public class MotanAdapterGlobalConfig {
+
+    private static final String TRUE_STR = "true";
+
+    public static final String APPLICATION = "application";
+    public static final String MOTAN = "motan";
+
+    public static final String BASE_SENTINEL_MOTAN_FILTER = "baseSentinelMotanFilter";
+    public static final String MOTAN_APP_CONTEXT = "motanAppContext";
+    public static final String SENTINEL_MOTAN_CONSUMER = "sentinelMotanConsumer";
+    public static final String SENTINEL_MOTAN_PROVIDER = "sentinelMotanProvider";
+
+    public static final String MOTAN_RES_NAME_WITH_PREFIX_KEY = "csp.sentinel.motan.resource.use.prefix";
+    public static final String MOTAN_PROVIDER_RES_NAME_PREFIX_KEY = "csp.sentinel.motan.resource.provider.prefix";
+    public static final String MOTAN_CONSUMER_RES_NAME_PREFIX_KEY = "csp.sentinel.motan.resource.consumer.prefix";
+
+    public static final String MOTAN_INTERFACE_GROUP_VERSION_ENABLED = "csp.sentinel.motan.interface.group.version.enabled";
+
+    private static final String DEFAULT_MOTAN_PROVIDER_PREFIX = "motan:provider:";
+    private static final String DEFAULT_MOTAN_CONSUMER_PREFIX = "motan:consumer:";
+
+    private static volatile MotanFallback consumerFallback = new DefaultMotanFallback();
+    private static volatile MotanFallback providerFallback = new DefaultMotanFallback();
+
+    private MotanAdapterGlobalConfig() {}
+
+    public static boolean isUsePrefix() {
+        return TRUE_STR.equalsIgnoreCase(SentinelConfig.getConfig(MOTAN_RES_NAME_WITH_PREFIX_KEY));
+    }
+
+    public static String getMotanProviderPrefix() {
+        if (isUsePrefix()) {
+            String config = SentinelConfig.getConfig(MOTAN_PROVIDER_RES_NAME_PREFIX_KEY);
+            return StringUtil.isNotBlank(config) ? config : DEFAULT_MOTAN_PROVIDER_PREFIX;
+        }
+        return null;
+    }
+
+    public static String getMotanConsumerPrefix() {
+        if (isUsePrefix()) {
+            String config = SentinelConfig.getConfig(MOTAN_CONSUMER_RES_NAME_PREFIX_KEY);
+            return StringUtil.isNotBlank(config) ? config : DEFAULT_MOTAN_CONSUMER_PREFIX;
+        }
+        return null;
+    }
+
+    public static Boolean getMotanInterfaceGroupAndVersionEnabled() {
+        return TRUE_STR.equalsIgnoreCase(SentinelConfig.getConfig(MOTAN_INTERFACE_GROUP_VERSION_ENABLED));
+    }
+
+    public static MotanFallback getConsumerFallback() {
+        return consumerFallback;
+    }
+
+    public static void setConsumerFallback(MotanFallback consumerFallback) {
+        AssertUtil.notNull(consumerFallback, "consumerFallback cannot be null");
+        MotanAdapterGlobalConfig.consumerFallback = consumerFallback;
+    }
+
+    public static MotanFallback getProviderFallback() {
+        return providerFallback;
+    }
+
+    public static void setProviderFallback(MotanFallback providerFallback) {
+        AssertUtil.notNull(providerFallback, "providerFallback cannot be null");
+        MotanAdapterGlobalConfig.providerFallback = providerFallback;
+    }
+}
diff --git a/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/fallback/DefaultMotanFallback.java b/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/fallback/DefaultMotanFallback.java
new file mode 100644
index 00000000..9d68fe7a
--- /dev/null
+++ b/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/fallback/DefaultMotanFallback.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 1999-2020 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
+ *
+ *      https://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.adapter.motan.fallback;
+
+import com.alibaba.csp.sentinel.slots.block.BlockException;
+import com.weibo.api.motan.rpc.Caller;
+import com.weibo.api.motan.rpc.DefaultResponse;
+import com.weibo.api.motan.rpc.Request;
+import com.weibo.api.motan.rpc.Response;
+
+/**
+ * @author zhangxn8
+ */
+public class DefaultMotanFallback implements MotanFallback{
+
+    @Override
+    public Response handle(Caller<?> caller, Request request, BlockException ex) {
+        DefaultResponse defaultResponse = new DefaultResponse();
+        defaultResponse.setException(ex.toRuntimeException());
+        defaultResponse.setRequestId(request.getRequestId());
+        defaultResponse.setAttachments(request.getAttachments());
+        defaultResponse.setRpcProtocolVersion(request.getRpcProtocolVersion());
+        return defaultResponse;
+    }
+}
diff --git a/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/fallback/MotanFallback.java b/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/fallback/MotanFallback.java
new file mode 100644
index 00000000..c2ee3d96
--- /dev/null
+++ b/sentinel-adapter/sentinel-motan-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/motan/fallback/MotanFallback.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 1999-2020 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
+ *
+ *      https://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.adapter.motan.fallback;
+
+import com.alibaba.csp.sentinel.slots.block.BlockException;
+import com.weibo.api.motan.rpc.Caller;
+import com.weibo.api.motan.rpc.Request;
+import com.weibo.api.motan.rpc.Response;
+
+/**
+ * @author zhangxn8
+ */
+public interface MotanFallback {
+
+    /**
+     * Handle the block exception and provide fallback result.
+     * @param caller
+     * @param request
+     * @param ex
+     * @return
+     */
+    Response handle(Caller<?> caller, Request request, BlockException ex);
+
+}
diff --git a/sentinel-adapter/sentinel-motan-adapter/src/main/resources/META-INF/services/com.weibo.api.motan.filter.Filter b/sentinel-adapter/sentinel-motan-adapter/src/main/resources/META-INF/services/com.weibo.api.motan.filter.Filter
new file mode 100644
index 00000000..7f7d1e29
--- /dev/null
+++ b/sentinel-adapter/sentinel-motan-adapter/src/main/resources/META-INF/services/com.weibo.api.motan.filter.Filter
@@ -0,0 +1,2 @@
+com.alibaba.csp.sentinel.adapter.motan.SentinelMotanProviderFilter
+com.alibaba.csp.sentinel.adapter.motan.SentinelMotanConsumerFilter
\ No newline at end of file
diff --git a/sentinel-demo/pom.xml b/sentinel-demo/pom.xml
index 4f3650c0..990c3950 100755
--- a/sentinel-demo/pom.xml
+++ b/sentinel-demo/pom.xml
@@ -44,6 +44,7 @@
         <module>sentinel-demo-jax-rs</module>
         <module>sentinel-demo-quarkus</module>
         <module>sentinel-demo-annotation-cdi-interceptor</module>
+        <module>sentinel-demo-motan</module>
     </modules>
 
     <dependencies>
diff --git a/sentinel-demo/sentinel-demo-motan/pom.xml b/sentinel-demo/sentinel-demo-motan/pom.xml
new file mode 100644
index 00000000..4f48a87d
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-motan/pom.xml
@@ -0,0 +1,68 @@
+<?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">
+    <parent>
+        <artifactId>sentinel-demo</artifactId>
+        <groupId>com.alibaba.csp</groupId>
+        <version>1.8.1-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>sentinel-demo-motan</artifactId>
+
+    <properties>
+        <motan.version>1.1.8</motan.version>
+        <slf4j.version>1.7.28</slf4j.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba.csp</groupId>
+            <artifactId>sentinel-motan-adapter</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.csp</groupId>
+            <artifactId>sentinel-transport-simple-http</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.weibo</groupId>
+            <artifactId>motan-core</artifactId>
+            <version>${motan.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.weibo</groupId>
+            <artifactId>motan-transport-netty4</artifactId>
+            <version>${motan.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>${slf4j.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>${slf4j.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${maven.compiler.version}</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                    <encoding>${java.encoding}</encoding>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/SentinelMotanConsumerService.java b/sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/SentinelMotanConsumerService.java
new file mode 100644
index 00000000..f6be190d
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/SentinelMotanConsumerService.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 1999-2020 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
+ *
+ *      https://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.demo.motan;
+
+import com.alibaba.csp.sentinel.demo.motan.service.MotanDemoService;
+import com.alibaba.csp.sentinel.slots.block.RuleConstant;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
+import com.weibo.api.motan.config.ProtocolConfig;
+import com.weibo.api.motan.config.RefererConfig;
+import com.weibo.api.motan.config.RegistryConfig;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author zhangxn8
+ */
+public class SentinelMotanConsumerService {
+
+    private static final String INTERFACE_RES_KEY = MotanDemoService.class.getName();
+    private static final String RES_KEY = INTERFACE_RES_KEY + ":hello(java.lang.String)";
+
+    public static void main(String[] args) {
+        RefererConfig<MotanDemoService> motanDemoServiceReferer = new RefererConfig<MotanDemoService>();
+        // 设置接口及实现类
+        motanDemoServiceReferer.setInterface(MotanDemoService.class);
+        // 配置服务的group以及版本号
+        motanDemoServiceReferer.setGroup("motan-demo-rpc");
+        motanDemoServiceReferer.setVersion("1.0");
+        motanDemoServiceReferer.setRequestTimeout(100000);
+
+        // 配置注册中心直连调用
+        RegistryConfig registry = new RegistryConfig();
+
+        //use direct registry
+        registry.setRegProtocol("direct");
+        registry.setAddress("127.0.0.1:8002");
+
+        // use ZooKeeper: 2181  or consul:8500 registry
+//        registry.setRegProtocol("consul");
+//        registry.setAddress("127.0.0.1:8500");
+        motanDemoServiceReferer.setRegistry(registry);
+
+        // 配置RPC协议
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setId("motan");
+        protocol.setName("motan");
+        motanDemoServiceReferer.setProtocol(protocol);
+        motanDemoServiceReferer.setDirectUrl("localhost:8002");  // 注册中心直连调用需添加此配置
+
+        initFlowRule(5, false);
+
+        // 使用服务
+        MotanDemoService service = motanDemoServiceReferer.getRef();
+        for (int i = 0 ;i< 5000 ;i++) {
+            System.out.println(service.hello("motan"));
+        }
+
+        System.exit(0);
+    }
+
+    private static void initFlowRule(int interfaceFlowLimit, boolean method) {
+        FlowRule flowRule = new FlowRule(INTERFACE_RES_KEY)
+                .setCount(interfaceFlowLimit)
+                .setGrade(RuleConstant.FLOW_GRADE_QPS);
+        List<FlowRule> list = new ArrayList<>();
+        if (method) {
+            FlowRule flowRule1 = new FlowRule(RES_KEY)
+                    .setCount(5)
+                    .setGrade(RuleConstant.FLOW_GRADE_QPS);
+            list.add(flowRule1);
+        }
+        list.add(flowRule);
+        FlowRuleManager.loadRules(list);
+    }
+}
diff --git a/sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/SentinelMotanProviderService.java b/sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/SentinelMotanProviderService.java
new file mode 100644
index 00000000..8d5c1f0b
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/SentinelMotanProviderService.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 1999-2020 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
+ *
+ *      https://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.demo.motan;
+
+import com.alibaba.csp.sentinel.demo.motan.service.MotanDemoService;
+import com.alibaba.csp.sentinel.demo.motan.service.impl.MotanDemoServiceImpl;
+import com.alibaba.csp.sentinel.init.InitExecutor;
+import com.weibo.api.motan.common.MotanConstants;
+import com.weibo.api.motan.config.ProtocolConfig;
+import com.weibo.api.motan.config.RegistryConfig;
+import com.weibo.api.motan.config.ServiceConfig;
+import com.weibo.api.motan.util.MotanSwitcherUtil;
+
+/**
+ * @author zhangxn8
+ */
+public class SentinelMotanProviderService {
+
+    public static void main(String[] args) {
+
+        InitExecutor.doInit();
+
+        ServiceConfig<MotanDemoService> motanDemoService = new ServiceConfig<MotanDemoService>();
+
+        // 设置接口及实现类
+        motanDemoService.setInterface(MotanDemoService.class);
+        motanDemoService.setRef(new MotanDemoServiceImpl());
+
+        // 配置服务的group以及版本号
+        motanDemoService.setGroup("motan-demo-rpc");
+        motanDemoService.setVersion("1.0");
+
+        // 配置注册中心直连调用
+        RegistryConfig registry = new RegistryConfig();
+
+        //use local registry
+        registry.setRegProtocol("local");
+
+        // use ZooKeeper: 2181  or consul:8500 registry
+//        registry.setRegProtocol("consul");
+//        registry.setAddress("127.0.0.1:8500");
+
+        // registry.setCheck("false"); //是否检查是否注册成功
+        motanDemoService.setRegistry(registry);
+
+        // 配置RPC协议
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setId("motan");
+        protocol.setName("motan");
+        motanDemoService.setProtocol(protocol);
+
+        motanDemoService.setExport("motan:8002");
+        motanDemoService.export();
+
+        MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true);
+
+        System.out.println("server start...");
+    }
+}
diff --git a/sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/service/MotanDemoService.java b/sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/service/MotanDemoService.java
new file mode 100644
index 00000000..c0f6a0d8
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/service/MotanDemoService.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 1999-2020 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
+ *
+ *      https://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.demo.motan.service;
+
+/**
+ * @author zhangxn8
+ */
+public interface MotanDemoService {
+
+    String hello(String name);
+
+}
diff --git a/sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/service/impl/MotanDemoServiceImpl.java b/sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/service/impl/MotanDemoServiceImpl.java
new file mode 100644
index 00000000..c5a3aa51
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-motan/src/main/java/com/alibaba/csp/sentinel/demo/motan/service/impl/MotanDemoServiceImpl.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 1999-2020 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
+ *
+ *      https://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.demo.motan.service.impl;
+
+import com.alibaba.csp.sentinel.demo.motan.service.MotanDemoService;
+
+/**
+ * @author zhangxn8
+ */
+public class MotanDemoServiceImpl implements MotanDemoService {
+
+    @Override
+    public String hello(String name) {
+        System.out.println(name);
+        return "Hello " + name + "!";
+    }
+}
diff --git a/sentinel-demo/sentinel-demo-motan/src/main/resources/sentinel.properties b/sentinel-demo/sentinel-demo-motan/src/main/resources/sentinel.properties
new file mode 100644
index 00000000..b55829bb
--- /dev/null
+++ b/sentinel-demo/sentinel-demo-motan/src/main/resources/sentinel.properties
@@ -0,0 +1 @@
+csp.sentinel.dashboard.server=localhost:8080
\ No newline at end of file