Skip to content

Commit

Permalink
Resilience4jDegrade
Browse files Browse the repository at this point in the history
  • Loading branch information
chentianming11 committed May 2, 2022
1 parent 3803fe9 commit 55c7d08
Show file tree
Hide file tree
Showing 29 changed files with 560 additions and 240 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,7 @@
public class DegradeProperty {

/**
* 是否启用熔断降级
* enable degrade
*/
private boolean enable = false;

/**
* 熔断降级类型
* degrade type
* 熔断降级类型。默认none,表示不启用熔断降级
*/
private String degradeType = RetrofitDegrade.NONE;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
Expand All @@ -16,21 +16,20 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import com.alibaba.csp.sentinel.SphU;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.lianjiatech.retrofit.spring.boot.core.AutoConfiguredRetrofitScannerRegistrar;
import com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory;
import com.github.lianjiatech.retrofit.spring.boot.core.BodyCallAdapterFactory;
import com.github.lianjiatech.retrofit.spring.boot.core.DefaultErrorDecoder;
import com.github.lianjiatech.retrofit.spring.boot.core.NoValidServiceInstanceChooser;
import com.github.lianjiatech.retrofit.spring.boot.core.ErrorDecoder;
import com.github.lianjiatech.retrofit.spring.boot.core.PathMatchInterceptorBdfProcessor;
import com.github.lianjiatech.retrofit.spring.boot.core.ResponseCallAdapterFactory;
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.ResourceNameParser;
import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitDegrade;
import com.github.lianjiatech.retrofit.spring.boot.degrade.resilience4j.Resilience4jRetrofitDegrade;
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;
Expand All @@ -39,6 +38,8 @@
import com.github.lianjiatech.retrofit.spring.boot.log.LoggingInterceptor;
import com.github.lianjiatech.retrofit.spring.boot.retry.RetryInterceptor;

import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import lombok.extern.slf4j.Slf4j;
import okhttp3.ConnectionPool;
import retrofit2.converter.jackson.JacksonConverterFactory;
Expand Down Expand Up @@ -69,8 +70,7 @@ public static PathMatchInterceptorBdfProcessor prototypeInterceptorBdfProcessor(

@Bean
@ConditionalOnMissingBean
public RetrofitConfigBean retrofitConfigBean(@Autowired(required = false) ResourceNameParser resourceNameParser,
@Autowired(required = false) RetrofitDegrade retrofitDegrade,
public RetrofitConfigBean retrofitConfigBean(@Autowired(required = false) RetrofitDegrade retrofitDegrade,
@Autowired(required = false) List<GlobalInterceptor> globalInterceptors,
@Autowired(required = false) List<NetworkInterceptor> networkInterceptors,
ServiceChooseInterceptor serviceChooseInterceptor, RetryInterceptor retryInterceptor,
Expand All @@ -79,7 +79,6 @@ public RetrofitConfigBean retrofitConfigBean(@Autowired(required = false) Resour
RetrofitConfigBean retrofitConfigBean = new RetrofitConfigBean(retrofitProperties);
retrofitConfigBean.setGlobalInterceptors(globalInterceptors);
retrofitConfigBean.setNetworkInterceptors(networkInterceptors);
retrofitConfigBean.setResourceNameParser(resourceNameParser);
retrofitConfigBean.setRetrofitDegrade(retrofitDegrade);
retrofitConfigBean.setServiceChooseInterceptor(serviceChooseInterceptor);
retrofitConfigBean.setRetryInterceptor(retryInterceptor);
Expand Down Expand Up @@ -116,8 +115,8 @@ public BasicTypeConverterFactory basicTypeConverterFactory() {
}

@Bean
public DefaultErrorDecoder defaultErrorDecoder() {
return new DefaultErrorDecoder();
public ErrorDecoder.DefaultErrorDecoder defaultErrorDecoder() {
return new ErrorDecoder.DefaultErrorDecoder();
}

@Bean
Expand All @@ -141,7 +140,7 @@ public LoggingInterceptor logInterceptor() {
@Bean
@ConditionalOnMissingBean
public ServiceInstanceChooser serviceInstanceChooser() {
return new NoValidServiceInstanceChooser();
return new ServiceInstanceChooser.NoValidServiceInstanceChooser();
}

@Bean
Expand All @@ -152,17 +151,18 @@ ServiceChooseInterceptor serviceChooseInterceptor(@Autowired ServiceInstanceChoo

@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "retrofit.degrade.enable", havingValue = "true")
public ResourceNameParser resourceNameParser() {
return new DefaultResourceNameParser();
@ConditionalOnClass(SphU.class)
@ConditionalOnProperty(name = "retrofit.degrade.degrade-type", havingValue = RetrofitDegrade.SENTINEL)
public RetrofitDegrade sentinelRetrofitDegrade() {
return new SentinelRetrofitDegrade();
}

@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "retrofit.degrade.degrade-type", havingValue = RetrofitDegrade.SENTINEL)
@ConditionalOnBean(ResourceNameParser.class)
public RetrofitDegrade retrofitDegrade(ResourceNameParser resourceNameParser) {
return new SentinelRetrofitDegrade(resourceNameParser);
@ConditionalOnClass(CircuitBreaker.class)
@ConditionalOnProperty(name = "retrofit.degrade.degrade-type", havingValue = RetrofitDegrade.RESILIENCE4J)
public RetrofitDegrade resilience4jRetrofitDegrade() {
return new Resilience4jRetrofitDegrade(CircuitBreakerRegistry.ofDefaults());
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.util.List;
import java.util.Map;

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;
Expand Down Expand Up @@ -40,8 +39,6 @@ public class RetrofitConfigBean {

private Class<? extends CallAdapter.Factory>[] globalCallAdapterFactoryClasses;

private ResourceNameParser resourceNameParser;

private RetrofitDegrade retrofitDegrade;

private LoggingInterceptor loggingInterceptor;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,6 @@ default RuntimeException exceptionDecode(Request request, Exception cause) {
return RetrofitException.errorUnknown(request, cause);
}

class DefaultErrorDecoder implements ErrorDecoder {}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
*
* @return ErrorDecoder
*/
Class<? extends ErrorDecoder> errorDecoder() default DefaultErrorDecoder.class;
Class<? extends ErrorDecoder> errorDecoder() default ErrorDecoder.DefaultErrorDecoder.class;

/**
* connection pool name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

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;
Expand Down Expand Up @@ -62,17 +61,14 @@ public RetrofitFactoryBean(Class<T> retrofitInterface) {
@Override
public T getObject() throws Exception {
T source = createRetrofit().create(retrofitInterface);
if (!isEnableDegrade(retrofitProperties.getDegrade(), retrofitInterface)) {
if (!isEnableDegrade(retrofitInterface)) {
return source;
}
retrofitConfigBean.getRetrofitDegrade().loadDegradeRules(retrofitInterface);
return DegradeProxy.create(source, retrofitInterface, applicationContext);
}

public boolean isEnableDegrade(DegradeProperty degradeProperty, Class<?> retrofitInterface) {
if (!degradeProperty.isEnable()) {
return false;
}
public boolean isEnableDegrade(Class<?> retrofitInterface) {
RetrofitDegrade retrofitDegrade = retrofitConfigBean.getRetrofitDegrade();
if (retrofitDegrade == null) {
return false;
Expand Down Expand Up @@ -105,7 +101,7 @@ private OkHttpClient createOkHttpClient()
throws IllegalAccessException, InstantiationException, InvocationTargetException {
OkHttpClient.Builder okHttpClientBuilder = createOkHttpClientBuilder();
RetrofitClient retrofitClient = retrofitInterface.getAnnotation(RetrofitClient.class);
if (isEnableDegrade(retrofitProperties.getDegrade(), retrofitInterface)) {
if (isEnableDegrade(retrofitInterface)) {
okHttpClientBuilder.addInterceptor(retrofitConfigBean.getRetrofitDegrade());
}
if (StringUtils.hasText(retrofitClient.serviceId())) {
Expand Down Expand Up @@ -162,7 +158,7 @@ private Method findOkHttpClientBuilderMethod() {
}

@SuppressWarnings("unchecked")
private List<Interceptor> findInterceptorByAnnotation() throws InstantiationException, IllegalAccessException {
private List<Interceptor> findInterceptorByAnnotation() {
Annotation[] classAnnotations = retrofitInterface.getAnnotations();
List<Interceptor> interceptors = new ArrayList<>();
// 找出被@InterceptMark标记的注解。Find the annotation marked by @InterceptMark
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.net.URI;

import com.github.lianjiatech.retrofit.spring.boot.exception.ServiceInstanceChooseException;

/**
* @author 陈添明
*/
Expand All @@ -16,4 +18,12 @@ public interface ServiceInstanceChooser {
*/
URI choose(String serviceId);

class NoValidServiceInstanceChooser implements ServiceInstanceChooser {

@Override
public URI choose(String serviceId) {
throw new ServiceInstanceChooseException("No valid service instance selector, Please configure it!");
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.github.lianjiatech.retrofit.spring.boot.degrade;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;

import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient;
import com.github.lianjiatech.retrofit.spring.boot.util.RetrofitUtils;

/**
* @author 陈添明
* @since 2022/5/1 9:54 下午
*/
public abstract class BaseRetrofitDegrade implements RetrofitDegrade, ResourceNameParser, EnvironmentAware {

protected static final String HTTP_OUT = "HTTP_OUT";

protected static final Map<Method, String> RESOURCE_NAME_CACHE = new ConcurrentHashMap<>(128);

protected Environment environment;

@Override
public String parseResourceName(Method method) {
String resourceName = RESOURCE_NAME_CACHE.get(method);
if (resourceName != null) {
return resourceName;
}
RetrofitClient retrofitClient = method.getDeclaringClass().getAnnotation(RetrofitClient.class);
String baseUrl = RetrofitUtils.convertBaseUrl(retrofitClient, retrofitClient.baseUrl(), environment);
HttpMethodPath httpMethodPath = parseHttpMethodPath(method);
resourceName = formatResourceName(baseUrl, httpMethodPath);
RESOURCE_NAME_CACHE.put(method, resourceName);
return resourceName;
}

protected String formatResourceName(String baseUrl, HttpMethodPath httpMethodPath) {
return String.format("%s:%s:%s", HTTP_OUT, httpMethodPath.getMethod(), baseUrl + httpMethodPath.getPath());
}

protected boolean isDefaultOrStatic(Method method) {
if (method.isDefault()) {
return true;
}
return Modifier.isStatic(method.getModifiers());
}

@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.github.lianjiatech.retrofit.spring.boot.degrade;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import retrofit2.http.DELETE;
import retrofit2.http.GET;
Expand All @@ -18,31 +16,12 @@
*/
public interface ResourceNameParser {

String HTTP_OUT = "HTTP_OUT";

Map<Method, String> RESOURCE_NAME_CACHE = new ConcurrentHashMap<>(128);

/**
* 提取资源名称,支持缓存
* @param method 方法
* @return 资源名称
*/
default String extractResourceNameCache(Method method) {
String resourceName = RESOURCE_NAME_CACHE.get(method);
if (resourceName != null) {
return resourceName;
}
resourceName = extractResourceName(method);
RESOURCE_NAME_CACHE.put(method, resourceName);
return resourceName;
}

/**
* 提取资源名称
* 解析资源名称
* @param method 方法
* @return 资源名称
*/
String extractResourceName(Method method);
String parseResourceName(Method method);

/**
* 解析方法路径
Expand Down Expand Up @@ -85,7 +64,6 @@ default HttpMethodPath parseHttpMethodPath(Method method) {
PATCH patch = method.getAnnotation(PATCH.class);
return new HttpMethodPath("PATCH", patch.value());
}

return null;
throw new UnsupportedOperationException("unsupported method!" + method);
}
}
Loading

0 comments on commit 55c7d08

Please sign in to comment.