diff --git a/spring-cloud-alibaba-sentinel/pom.xml b/spring-cloud-alibaba-sentinel/pom.xml
index b4f63c9f..d635b2a0 100644
--- a/spring-cloud-alibaba-sentinel/pom.xml
+++ b/spring-cloud-alibaba-sentinel/pom.xml
@@ -35,6 +35,13 @@
sentinel-dubbo-adapter
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+ provided
+ true
+
+
org.springframework.cloud
spring-cloud-alibaba-sentinel-datasource
diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/feign/SentinelContractHolder.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/feign/SentinelContractHolder.java
new file mode 100644
index 00000000..6056e800
--- /dev/null
+++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/feign/SentinelContractHolder.java
@@ -0,0 +1,55 @@
+/*
+ * 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.feign;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import feign.Contract;
+import feign.MethodMetadata;
+
+/**
+ *
+ * Using static field {@link SentinelContractHolder#metadataMap} to hold
+ * {@link MethodMetadata} data
+ *
+ * @author Jim
+ */
+public class SentinelContractHolder implements Contract {
+
+ private final Contract delegate;
+
+ /**
+ * map key is constructed by ClassFullName + configKey. configKey is constructed by
+ * {@link feign.Feign#configKey}
+ */
+ public final static Map metadataMap = new HashMap();
+
+ public SentinelContractHolder(Contract delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public List parseAndValidatateMetadata(Class> targetType) {
+ List metadatas = delegate.parseAndValidatateMetadata(targetType);
+ metadatas.forEach(metadata -> metadataMap
+ .put(targetType.getName() + metadata.configKey(), metadata));
+ return metadatas;
+ }
+
+}
diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/feign/SentinelFeign.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/feign/SentinelFeign.java
new file mode 100644
index 00000000..5da3c1bc
--- /dev/null
+++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/feign/SentinelFeign.java
@@ -0,0 +1,148 @@
+/*
+ * 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.feign;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+import org.springframework.beans.BeansException;
+import org.springframework.cloud.openfeign.FeignContext;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.util.ReflectionUtils;
+
+import feign.Contract;
+import feign.Feign;
+import feign.InvocationHandlerFactory;
+import feign.Target;
+import feign.hystrix.FallbackFactory;
+import feign.hystrix.HystrixFeign;
+
+/**
+ * {@link Feign.Builder} like {@link HystrixFeign.Builder}
+ *
+ * @author Jim
+ */
+public class SentinelFeign {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder extends Feign.Builder
+ implements ApplicationContextAware {
+
+ private Contract contract = new Contract.Default();
+
+ private ApplicationContext applicationContext;
+
+ private FeignContext feignContext;
+
+ @Override
+ public Feign.Builder invocationHandlerFactory(
+ InvocationHandlerFactory invocationHandlerFactory) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Builder contract(Contract contract) {
+ this.contract = contract;
+ return this;
+ }
+
+ @Override
+ public Feign build() {
+ super.invocationHandlerFactory(new InvocationHandlerFactory() {
+ @Override
+ public InvocationHandler create(Target target,
+ Map dispatch) {
+ // using reflect get fallback and fallbackFactory properties from
+ // FeignClientFactoryBean because FeignClientFactoryBean is a package
+ // level class, we can not use it in our package
+ Object feignClientFactoryBean = Builder.this.applicationContext
+ .getBean("&" + target.type().getName());
+
+ Class fallback = (Class) getFieldValue(feignClientFactoryBean,
+ "fallback");
+ Class fallbackFactory = (Class) getFieldValue(feignClientFactoryBean,
+ "fallbackFactory");
+ String name = (String) getFieldValue(feignClientFactoryBean, "name");
+
+ Object fallbackInstance;
+ FallbackFactory fallbackFactoryInstance;
+ // check fallback and fallbackFactory properties
+ if (void.class != fallback) {
+ fallbackInstance = getFromContext(name, "fallback", fallback,
+ target);
+ return new SentinelInvocationHandler(target, dispatch,
+ new FallbackFactory.Default(fallbackInstance));
+ }
+ if (void.class != fallbackFactory) {
+ fallbackFactoryInstance = (FallbackFactory) getFromContext(name,
+ "fallbackFactory", fallbackFactory, target);
+ return new SentinelInvocationHandler(target, dispatch,
+ fallbackFactoryInstance);
+ }
+ return new SentinelInvocationHandler(target, dispatch);
+ }
+
+ private Object getFromContext(String name, String type,
+ Class fallbackType, Target target) {
+ Object fallbackInstance = feignContext.getInstance(name,
+ fallbackType);
+ if (fallbackInstance == null) {
+ throw new IllegalStateException(String.format(
+ "No %s instance of type %s found for feign client %s",
+ type, fallbackType, name));
+ }
+
+ if (!target.type().isAssignableFrom(fallbackType)) {
+ throw new IllegalStateException(String.format(
+ "Incompatible %s instance. Fallback/fallbackFactory of type %s is not assignable to %s for feign client %s",
+ type, fallbackType, target.type(), name));
+ }
+ return fallbackInstance;
+ }
+ });
+
+ super.contract(new SentinelContractHolder(contract));
+ return super.build();
+ }
+
+ private Object getFieldValue(Object instance, String fieldName) {
+ Field field = ReflectionUtils.findField(instance.getClass(), fieldName);
+ field.setAccessible(true);
+ try {
+ return field.get(instance);
+ }
+ catch (IllegalAccessException e) {
+ // ignore
+ }
+ return null;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ this.applicationContext = applicationContext;
+ feignContext = this.applicationContext.getBean(FeignContext.class);
+ }
+ }
+
+}
diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/feign/SentinelFeignAutoConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/feign/SentinelFeignAutoConfiguration.java
new file mode 100644
index 00000000..1ed20e1b
--- /dev/null
+++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/feign/SentinelFeignAutoConfiguration.java
@@ -0,0 +1,45 @@
+/*
+ * 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.feign;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+
+import com.alibaba.csp.sentinel.SphU;
+
+import feign.Feign;
+
+/**
+ * @author Jim
+ */
+@Configuration
+@ConditionalOnClass({ SphU.class, Feign.class })
+public class SentinelFeignAutoConfiguration {
+
+ @Bean
+ @Scope("prototype")
+ @ConditionalOnMissingBean
+ @ConditionalOnProperty(name = "feign.sentinel.enabled")
+ public Feign.Builder feignSentinelBuilder() {
+ return SentinelFeign.builder();
+ }
+
+}
diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/feign/SentinelInvocationHandler.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/feign/SentinelInvocationHandler.java
new file mode 100644
index 00000000..809879cc
--- /dev/null
+++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/feign/SentinelInvocationHandler.java
@@ -0,0 +1,172 @@
+/*
+ * 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.feign;
+
+import static feign.Util.checkNotNull;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+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 feign.Feign;
+import feign.InvocationHandlerFactory.MethodHandler;
+import feign.MethodMetadata;
+import feign.Target;
+import feign.hystrix.FallbackFactory;
+
+/**
+ * {@link InvocationHandler} handle invocation that protected by Sentinel
+ *
+ * @author Jim
+ */
+public class SentinelInvocationHandler implements InvocationHandler {
+
+ private final Target> target;
+ private final Map dispatch;
+
+ private FallbackFactory fallbackFactory;
+ private Map fallbackMethodMap;
+
+ SentinelInvocationHandler(Target> target, Map dispatch,
+ FallbackFactory fallbackFactory) {
+ this.target = checkNotNull(target, "target");
+ this.dispatch = checkNotNull(dispatch, "dispatch");
+ this.fallbackFactory = fallbackFactory;
+ this.fallbackMethodMap = toFallbackMethod(dispatch);
+ }
+
+ SentinelInvocationHandler(Target> target, Map dispatch) {
+ this.target = checkNotNull(target, "target");
+ this.dispatch = checkNotNull(dispatch, "dispatch");
+ }
+
+ @Override
+ public Object invoke(final Object proxy, final Method method, final Object[] args)
+ throws Throwable {
+ if ("equals".equals(method.getName())) {
+ try {
+ Object otherHandler = args.length > 0 && args[0] != null
+ ? Proxy.getInvocationHandler(args[0])
+ : null;
+ return equals(otherHandler);
+ }
+ catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
+ else if ("hashCode".equals(method.getName())) {
+ return hashCode();
+ }
+ else if ("toString".equals(method.getName())) {
+ return toString();
+ }
+
+ Object result;
+ MethodHandler methodHandler = this.dispatch.get(method);
+ // only handle by HardCodedTarget
+ if (target instanceof Target.HardCodedTarget) {
+ Target.HardCodedTarget hardCodedTarget = (Target.HardCodedTarget) target;
+ MethodMetadata methodMetadata = SentinelContractHolder.metadataMap
+ .get(method.getDeclaringClass().getName()
+ + Feign.configKey(method.getDeclaringClass(), method));
+ // resource default is HttpMethod:protocol://url
+ String resourceName = methodMetadata.template().method().toUpperCase() + ":"
+ + hardCodedTarget.url() + methodMetadata.template().url();
+ Entry entry = null;
+ try {
+ ContextUtil.enter(resourceName);
+ entry = SphU.entry(resourceName, EntryType.OUT, 1, args);
+ result = methodHandler.invoke(args);
+ }
+ catch (Throwable ex) {
+ // fallback handle
+ if (!BlockException.isBlockException(ex)) {
+ Tracer.trace(ex);
+ }
+ if (fallbackFactory != null) {
+ try {
+ Object fallbackResult = fallbackMethodMap.get(method)
+ .invoke(fallbackFactory.create(ex), args);
+ return fallbackResult;
+ }
+ catch (IllegalAccessException e) {
+ // shouldn't happen as method is public due to being an interface
+ throw new AssertionError(e);
+ }
+ catch (InvocationTargetException e) {
+ throw new AssertionError(e.getCause());
+ }
+ }
+ else {
+ // throw exception if fallbackFactory is null
+ throw ex;
+ }
+ }
+ finally {
+ if (entry != null) {
+ entry.exit();
+ }
+ ContextUtil.exit();
+ }
+ }
+ else {
+ // other target type using default strategy
+ result = methodHandler.invoke(args);
+ }
+
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof SentinelInvocationHandler) {
+ SentinelInvocationHandler other = (SentinelInvocationHandler) obj;
+ return target.equals(other.target);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return target.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return target.toString();
+ }
+
+ static Map toFallbackMethod(Map dispatch) {
+ Map result = new LinkedHashMap<>();
+ for (Method method : dispatch.keySet()) {
+ method.setAccessible(true);
+ result.put(method, method);
+ }
+ return result;
+ }
+
+}
diff --git a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/spring.factories
index ae146be4..702bb5bb 100644
--- a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/spring.factories
@@ -1,4 +1,5 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.alibaba.sentinel.SentinelWebAutoConfiguration,\
org.springframework.cloud.alibaba.sentinel.endpoint.SentinelEndpointAutoConfiguration,\
-org.springframework.cloud.alibaba.sentinel.custom.SentinelAutoConfiguration
+org.springframework.cloud.alibaba.sentinel.custom.SentinelAutoConfiguration,\
+org.springframework.cloud.alibaba.sentinel.feign.SentinelFeignAutoConfiguration