diff --git a/pom.xml b/pom.xml index 6a978da..9f096d5 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,7 @@ 4.13.1 1.3.2 1.7.25 - 2.0.0.RELEASE + 2.0.9.RELEASE 3.14.9 1.17.5 1.6.3 @@ -59,7 +59,7 @@ org.springframework.cloud spring-cloud-commons - ${spring-boot.version} + 2.0.4.RELEASE provided @@ -166,6 +166,12 @@ ${sentinel.version} provided + + io.github.resilience4j + resilience4j-circuitbreaker + 1.7.1 + provided + diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/DegradeProperty.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/DegradeProperty.java index 21d8fea..8684e69 100644 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/DegradeProperty.java +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/DegradeProperty.java @@ -1,6 +1,6 @@ package com.github.lianjiatech.retrofit.spring.boot.config; -import com.github.lianjiatech.retrofit.spring.boot.degrade.DegradeType; +import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitDegrade; import lombok.Data; @@ -11,7 +11,7 @@ public class DegradeProperty { /** - * 启用熔断降级 + * 是否启用熔断降级 * enable degrade */ private boolean enable = false; @@ -20,5 +20,5 @@ public class DegradeProperty { * 熔断降级类型 * degrade type */ - private DegradeType degradeType = DegradeType.SENTINEL; + private String degradeType = RetrofitDegrade.NONE; } diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitAutoConfiguration.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitAutoConfiguration.java index 3140ccd..0ce0e32 100644 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitAutoConfiguration.java +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitAutoConfiguration.java @@ -29,9 +29,9 @@ import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitFactoryBean; import com.github.lianjiatech.retrofit.spring.boot.core.ServiceInstanceChooser; import com.github.lianjiatech.retrofit.spring.boot.degrade.DefaultResourceNameParser; -import com.github.lianjiatech.retrofit.spring.boot.degrade.DegradeInterceptor; import com.github.lianjiatech.retrofit.spring.boot.degrade.ResourceNameParser; -import com.github.lianjiatech.retrofit.spring.boot.degrade.sentinel.SentinelDegradeInterceptor; +import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitDegrade; +import com.github.lianjiatech.retrofit.spring.boot.degrade.sentinel.SentinelRetrofitDegrade; import com.github.lianjiatech.retrofit.spring.boot.interceptor.ErrorDecoderInterceptor; import com.github.lianjiatech.retrofit.spring.boot.interceptor.GlobalInterceptor; import com.github.lianjiatech.retrofit.spring.boot.interceptor.NetworkInterceptor; @@ -70,7 +70,7 @@ public static PathMatchInterceptorBdfProcessor prototypeInterceptorBdfProcessor( @Bean @ConditionalOnMissingBean public RetrofitConfigBean retrofitConfigBean(@Autowired(required = false) ResourceNameParser resourceNameParser, - @Autowired(required = false) DegradeInterceptor degradeInterceptor, + @Autowired(required = false) RetrofitDegrade retrofitDegrade, @Autowired(required = false) List globalInterceptors, @Autowired(required = false) List networkInterceptors, ServiceChooseInterceptor serviceChooseInterceptor, RetryInterceptor retryInterceptor, @@ -80,7 +80,7 @@ public RetrofitConfigBean retrofitConfigBean(@Autowired(required = false) Resour retrofitConfigBean.setGlobalInterceptors(globalInterceptors); retrofitConfigBean.setNetworkInterceptors(networkInterceptors); retrofitConfigBean.setResourceNameParser(resourceNameParser); - retrofitConfigBean.setDegradeInterceptor(degradeInterceptor); + retrofitConfigBean.setRetrofitDegrade(retrofitDegrade); retrofitConfigBean.setServiceChooseInterceptor(serviceChooseInterceptor); retrofitConfigBean.setRetryInterceptor(retryInterceptor); retrofitConfigBean.setLoggingInterceptor(loggingInterceptor); @@ -159,10 +159,10 @@ public ResourceNameParser resourceNameParser() { @Bean @ConditionalOnMissingBean - @ConditionalOnProperty(name = "retrofit.degrade.degrade-type", havingValue = "sentinel") + @ConditionalOnProperty(name = "retrofit.degrade.degrade-type", havingValue = RetrofitDegrade.SENTINEL) @ConditionalOnBean(ResourceNameParser.class) - public DegradeInterceptor degradeInterceptor(ResourceNameParser resourceNameParser) { - return new SentinelDegradeInterceptor(resourceNameParser); + public RetrofitDegrade retrofitDegrade(ResourceNameParser resourceNameParser) { + return new SentinelRetrofitDegrade(resourceNameParser); } @Bean diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitConfigBean.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitConfigBean.java index f7b5016..420039e 100644 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitConfigBean.java +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitConfigBean.java @@ -4,8 +4,8 @@ import java.util.List; import java.util.Map; -import com.github.lianjiatech.retrofit.spring.boot.degrade.DegradeInterceptor; import com.github.lianjiatech.retrofit.spring.boot.degrade.ResourceNameParser; +import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitDegrade; import com.github.lianjiatech.retrofit.spring.boot.interceptor.ErrorDecoderInterceptor; import com.github.lianjiatech.retrofit.spring.boot.interceptor.GlobalInterceptor; import com.github.lianjiatech.retrofit.spring.boot.interceptor.NetworkInterceptor; @@ -42,7 +42,7 @@ public class RetrofitConfigBean { private ResourceNameParser resourceNameParser; - private DegradeInterceptor degradeInterceptor; + private RetrofitDegrade retrofitDegrade; private LoggingInterceptor loggingInterceptor; diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitFactoryBean.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitFactoryBean.java index f114424..dfc5d97 100644 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitFactoryBean.java +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitFactoryBean.java @@ -22,19 +22,15 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; import com.github.lianjiatech.retrofit.spring.boot.config.DegradeProperty; import com.github.lianjiatech.retrofit.spring.boot.config.RetrofitConfigBean; import com.github.lianjiatech.retrofit.spring.boot.config.RetrofitProperties; import com.github.lianjiatech.retrofit.spring.boot.degrade.DegradeProxy; -import com.github.lianjiatech.retrofit.spring.boot.degrade.DegradeType; -import com.github.lianjiatech.retrofit.spring.boot.degrade.sentinel.SentinelDegrade; +import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitDegrade; import com.github.lianjiatech.retrofit.spring.boot.interceptor.BasePathMatchInterceptor; import com.github.lianjiatech.retrofit.spring.boot.interceptor.Intercept; import com.github.lianjiatech.retrofit.spring.boot.interceptor.InterceptMark; import com.github.lianjiatech.retrofit.spring.boot.interceptor.Intercepts; -import com.github.lianjiatech.retrofit.spring.boot.util.AnnotationExtendUtils; import com.github.lianjiatech.retrofit.spring.boot.util.AppContextUtils; import com.github.lianjiatech.retrofit.spring.boot.util.BeanExtendUtils; import com.github.lianjiatech.retrofit.spring.boot.util.RetrofitUtils; @@ -66,53 +62,22 @@ public RetrofitFactoryBean(Class retrofitInterface) { @Override public T getObject() throws Exception { T source = createRetrofit().create(retrofitInterface); - if (!isEnableSentinelDegrade(retrofitProperties.getDegrade(), retrofitInterface)) { + if (!isEnableDegrade(retrofitProperties.getDegrade(), retrofitInterface)) { return source; } - // 启用代理 - loadDegradeRules(); + retrofitConfigBean.getRetrofitDegrade().loadDegradeRules(retrofitInterface); return DegradeProxy.create(source, retrofitInterface, applicationContext); } - public boolean isEnableSentinelDegrade(DegradeProperty degradeProperty, Class retrofitInterface) { + public boolean isEnableDegrade(DegradeProperty degradeProperty, Class retrofitInterface) { if (!degradeProperty.isEnable()) { return false; } - return AnnotationExtendUtils.isAnnotationPresent(retrofitInterface, SentinelDegrade.class); - } - - private void loadDegradeRules() { - if (retrofitProperties.getDegrade().getDegradeType() == DegradeType.SENTINEL) { - loadSentinelDegradeRules(); - } - } - - private void loadSentinelDegradeRules() { - // 读取熔断配置 - Method[] methods = retrofitInterface.getMethods(); - List rules = new ArrayList<>(); - for (Method method : methods) { - if (method.isDefault()) { - continue; - } - int modifiers = method.getModifiers(); - if (Modifier.isStatic(modifiers)) { - continue; - } - // 获取熔断配置 - SentinelDegrade sentinelDegrade = AnnotationExtendUtils.findAnnotation(method, SentinelDegrade.class); - if (sentinelDegrade == null) { - continue; - } - - DegradeRule degradeRule = new DegradeRule() - .setCount(sentinelDegrade.count()) - .setTimeWindow(sentinelDegrade.timeWindow()) - .setGrade(sentinelDegrade.grade()); - degradeRule.setResource(retrofitConfigBean.getResourceNameParser().extractResourceNameCache(method)); - rules.add(degradeRule); + RetrofitDegrade retrofitDegrade = retrofitConfigBean.getRetrofitDegrade(); + if (retrofitDegrade == null) { + return false; } - DegradeRuleManager.loadRules(rules); + return retrofitDegrade.isEnableDegrade(retrofitInterface); } @Override @@ -140,8 +105,8 @@ private OkHttpClient createOkHttpClient() throws IllegalAccessException, InstantiationException, InvocationTargetException { OkHttpClient.Builder okHttpClientBuilder = createOkHttpClientBuilder(); RetrofitClient retrofitClient = retrofitInterface.getAnnotation(RetrofitClient.class); - if (isEnableSentinelDegrade(retrofitProperties.getDegrade(), retrofitInterface)) { - okHttpClientBuilder.addInterceptor(retrofitConfigBean.getDegradeInterceptor()); + if (isEnableDegrade(retrofitProperties.getDegrade(), retrofitInterface)) { + okHttpClientBuilder.addInterceptor(retrofitConfigBean.getRetrofitDegrade()); } if (StringUtils.hasText(retrofitClient.serviceId())) { okHttpClientBuilder.addInterceptor(retrofitConfigBean.getServiceChooseInterceptor()); diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/DegradeInterceptor.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/DegradeInterceptor.java deleted file mode 100644 index 7562774..0000000 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/DegradeInterceptor.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.degrade; - -import okhttp3.Interceptor; - -/** - * @author 陈添明 - * @since 2022/4/30 3:34 下午 - */ -public interface DegradeInterceptor extends Interceptor {} diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/DegradeType.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/DegradeType.java deleted file mode 100644 index 0b25069..0000000 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/DegradeType.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.degrade; - -/** - * @author 陈添明 - */ -public enum DegradeType { - - SENTINEL, - -} diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/RetrofitDegrade.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/RetrofitDegrade.java new file mode 100644 index 0000000..0ab7b44 --- /dev/null +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/RetrofitDegrade.java @@ -0,0 +1,27 @@ +package com.github.lianjiatech.retrofit.spring.boot.degrade; + +import okhttp3.Interceptor; + +/** + * @author 陈添明 + * @since 2022/4/30 3:34 下午 + */ +public interface RetrofitDegrade extends Interceptor { + + String NONE = "none"; + String SENTINEL = "sentinel"; + + /** + * 对于指定Retrofit接口,是否允许降级 + * @param retrofitInterface Retrofit接口 + * @return 是否允许降级 + */ + boolean isEnableDegrade(Class retrofitInterface); + + /** + * 加载指定Retrofit接口下的降级规则 + * @param retrofitInterface Retrofit接口 + */ + void loadDegradeRules(Class retrofitInterface); + +} diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/release4j/Release4jRetrofitDegrade.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/release4j/Release4jRetrofitDegrade.java new file mode 100644 index 0000000..cef8bba --- /dev/null +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/release4j/Release4jRetrofitDegrade.java @@ -0,0 +1,31 @@ +package com.github.lianjiatech.retrofit.spring.boot.degrade.release4j; + +import java.io.IOException; + +import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitDegrade; + +import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; +import okhttp3.Response; + +/** + * @author 陈添明 + * @since 2022/5/1 8:02 下午 + */ +public class Release4jRetrofitDegrade implements RetrofitDegrade { + + @Override + public boolean isEnableDegrade(Class retrofitInterface) { + return false; + } + + @Override + public void loadDegradeRules(Class retrofitInterface) { + CircuitBreakerRegistry registry = new CircuitBreakerRegistry.Builder() + .build(); + } + + @Override + public Response intercept(Chain chain) throws IOException { + return null; + } +} diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/sentinel/SentinelDegradeInterceptor.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/sentinel/SentinelDegradeInterceptor.java deleted file mode 100644 index 577e753..0000000 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/sentinel/SentinelDegradeInterceptor.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.degrade.sentinel; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.Objects; - -import com.alibaba.csp.sentinel.Entry; -import com.alibaba.csp.sentinel.EntryType; -import com.alibaba.csp.sentinel.ResourceTypeConstants; -import com.alibaba.csp.sentinel.SphU; -import com.alibaba.csp.sentinel.slots.block.BlockException; -import com.github.lianjiatech.retrofit.spring.boot.degrade.DegradeInterceptor; -import com.github.lianjiatech.retrofit.spring.boot.degrade.ResourceNameParser; -import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitBlockException; -import com.github.lianjiatech.retrofit.spring.boot.util.AnnotationExtendUtils; - -import okhttp3.Request; -import okhttp3.Response; -import retrofit2.Invocation; - -/** - * @author 陈添明 - */ -public class SentinelDegradeInterceptor implements DegradeInterceptor { - - protected final ResourceNameParser resourceNameParser; - - public SentinelDegradeInterceptor(ResourceNameParser resourceNameParser) { - this.resourceNameParser = resourceNameParser; - } - - @Override - public Response intercept(Chain chain) throws IOException { - Request request = chain.request(); - Method method = Objects.requireNonNull(request.tag(Invocation.class)).method(); - if (AnnotationExtendUtils.findAnnotation(method, SentinelDegrade.class) == null) { - return chain.proceed(request); - } - String resourceName = resourceNameParser.extractResourceNameCache(method); - Entry entry = null; - try { - entry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_WEB, EntryType.OUT); - return chain.proceed(request); - } catch (BlockException e) { - throw new RetrofitBlockException(e); - } finally { - if (entry != null) { - entry.exit(); - } - } - } -} diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/sentinel/SentinelRetrofitDegrade.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/sentinel/SentinelRetrofitDegrade.java new file mode 100644 index 0000000..41135c4 --- /dev/null +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/sentinel/SentinelRetrofitDegrade.java @@ -0,0 +1,91 @@ +package com.github.lianjiatech.retrofit.spring.boot.degrade.sentinel; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import com.alibaba.csp.sentinel.Entry; +import com.alibaba.csp.sentinel.EntryType; +import com.alibaba.csp.sentinel.ResourceTypeConstants; +import com.alibaba.csp.sentinel.SphU; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; +import com.github.lianjiatech.retrofit.spring.boot.degrade.ResourceNameParser; +import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitBlockException; +import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitDegrade; +import com.github.lianjiatech.retrofit.spring.boot.util.AnnotationExtendUtils; + +import okhttp3.Request; +import okhttp3.Response; +import retrofit2.Invocation; + +/** + * @author 陈添明 + */ +public class SentinelRetrofitDegrade implements RetrofitDegrade { + + protected final ResourceNameParser resourceNameParser; + + public SentinelRetrofitDegrade(ResourceNameParser resourceNameParser) { + this.resourceNameParser = resourceNameParser; + } + + @Override + public boolean isEnableDegrade(Class retrofitInterface) { + // 类或者方法上存在@SentinelDegrade -> 允许降级 + return AnnotationExtendUtils.isAnnotationPresent(retrofitInterface, SentinelDegrade.class); + } + + @Override + public void loadDegradeRules(Class retrofitInterface) { + Method[] methods = retrofitInterface.getMethods(); + List rules = new ArrayList<>(); + for (Method method : methods) { + if (method.isDefault()) { + continue; + } + int modifiers = method.getModifiers(); + if (Modifier.isStatic(modifiers)) { + continue; + } + // 获取熔断配置 + SentinelDegrade sentinelDegrade = AnnotationExtendUtils.findAnnotation(method, SentinelDegrade.class); + if (sentinelDegrade == null) { + continue; + } + DegradeRule degradeRule = new DegradeRule() + .setCount(sentinelDegrade.count()) + .setTimeWindow(sentinelDegrade.timeWindow()) + .setGrade(sentinelDegrade.grade()); + degradeRule.setResource(resourceNameParser.extractResourceNameCache(method)); + rules.add(degradeRule); + } + DegradeRuleManager.loadRules(rules); + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Method method = Objects.requireNonNull(request.tag(Invocation.class)).method(); + if (AnnotationExtendUtils.findAnnotation(method, SentinelDegrade.class) == null) { + return chain.proceed(request); + } + String resourceName = resourceNameParser.extractResourceNameCache(method); + Entry entry = null; + try { + entry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_WEB, EntryType.OUT); + return chain.proceed(request); + } catch (BlockException e) { + throw new RetrofitBlockException(e); + } finally { + if (entry != null) { + entry.exit(); + } + } + } + +} diff --git a/src/test/resources/default-config.yml b/src/test/resources/default-config.yml index 5e062f5..303ab9c 100644 --- a/src/test/resources/default-config.yml +++ b/src/test/resources/default-config.yml @@ -44,7 +44,7 @@ retrofit: # 是否启用熔断降级 enable: false # 熔断降级实现方式 - degrade-type: sentinel + degrade-type: none # 全局连接超时时间 global-connect-timeout-ms: 10000