Skip to content

Commit

Permalink
add: 熔断限流第一版优化方案
Browse files Browse the repository at this point in the history
  • Loading branch information
yukdawn committed Apr 5, 2022
1 parent 95f340d commit 6fe63fa
Show file tree
Hide file tree
Showing 10 changed files with 217 additions and 190 deletions.
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@
<version>${sentinel.version}</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-spring -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring</artifactId>
<version>1.7.1</version>
<scope>provided</scope>
</dependency>

</dependencies>

<distributionManagement>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import com.github.lianjiatech.retrofit.spring.boot.degrade.DegradeRuleRegister;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
Expand All @@ -29,7 +31,6 @@
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.BaseResourceNameParser;
import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitDegradeRuleInitializer;
import com.github.lianjiatech.retrofit.spring.boot.interceptor.GlobalAndNetworkInterceptorFinder;
import com.github.lianjiatech.retrofit.spring.boot.interceptor.ServiceInstanceChooserInterceptor;
import com.github.lianjiatech.retrofit.spring.boot.retry.BaseRetryInterceptor;
Expand Down Expand Up @@ -71,7 +72,7 @@ public GlobalAndNetworkInterceptorFinder globalAndNetworkInterceptorFinder() {

@Bean
@ConditionalOnMissingBean
public RetrofitConfigBean retrofitConfigBean() throws IllegalAccessException, InstantiationException {
public RetrofitConfigBean retrofitConfigBean(ObjectProvider<DegradeRuleRegister> degradeRuleRegisterObjectProvider) throws IllegalAccessException, InstantiationException {
RetrofitConfigBean retrofitConfigBean =
new RetrofitConfigBean(retrofitProperties, globalAndNetworkInterceptorFinder());
// Initialize the connection pool
Expand Down Expand Up @@ -121,6 +122,9 @@ public RetrofitConfigBean retrofitConfigBean() throws IllegalAccessException, In
Class<? extends BaseResourceNameParser> resourceNameParser = degrade.getResourceNameParser();
retrofitConfigBean.setResourceNameParser(resourceNameParser.newInstance());

// degrade register
retrofitConfigBean.setDegradeRuleRegister(degradeRuleRegisterObjectProvider.getIfAvailable());

return retrofitConfigBean;
}

Expand All @@ -145,11 +149,6 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
this.applicationContext = applicationContext;
}

@Bean
public RetrofitDegradeRuleInitializer retrofitDegradeRuleInitializer() {
return new RetrofitDegradeRuleInitializer(retrofitProperties.getDegrade());
}

@Configuration
@Import({AutoConfiguredRetrofitScannerRegistrar.class})
@ConditionalOnMissingBean(RetrofitFactoryBean.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Map;

import com.github.lianjiatech.retrofit.spring.boot.degrade.BaseResourceNameParser;
import com.github.lianjiatech.retrofit.spring.boot.degrade.DegradeRuleRegister;
import com.github.lianjiatech.retrofit.spring.boot.interceptor.GlobalAndNetworkInterceptorFinder;
import com.github.lianjiatech.retrofit.spring.boot.interceptor.GlobalInterceptor;
import com.github.lianjiatech.retrofit.spring.boot.interceptor.NetworkInterceptor;
Expand Down Expand Up @@ -37,6 +38,8 @@ public class RetrofitConfigBean {

private BaseResourceNameParser resourceNameParser;

private DegradeRuleRegister degradeRuleRegister;

public RetrofitProperties getRetrofitProperties() {
return retrofitProperties;
}
Expand Down Expand Up @@ -105,4 +108,12 @@ public BaseResourceNameParser getResourceNameParser() {
public void setResourceNameParser(BaseResourceNameParser resourceNameParser) {
this.resourceNameParser = resourceNameParser;
}

public DegradeRuleRegister getDegradeRuleRegister() {
return degradeRuleRegister;
}

public void setDegradeRuleRegister(DegradeRuleRegister degradeRuleRegister) {
this.degradeRuleRegister = degradeRuleRegister;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.github.lianjiatech.retrofit.spring.boot.degrade.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
Expand All @@ -36,14 +33,6 @@
import com.github.lianjiatech.retrofit.spring.boot.config.LogProperty;
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.BaseResourceNameParser;
import com.github.lianjiatech.retrofit.spring.boot.degrade.Degrade;
import com.github.lianjiatech.retrofit.spring.boot.degrade.DegradeStrategy;
import com.github.lianjiatech.retrofit.spring.boot.degrade.DegradeType;
import com.github.lianjiatech.retrofit.spring.boot.degrade.FallbackFactory;
import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitDegradeRule;
import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitDegradeRuleInitializer;
import com.github.lianjiatech.retrofit.spring.boot.degrade.SentinelDegradeInterceptor;
import com.github.lianjiatech.retrofit.spring.boot.interceptor.BaseLoggingInterceptor;
import com.github.lianjiatech.retrofit.spring.boot.interceptor.BasePathMatchInterceptor;
import com.github.lianjiatech.retrofit.spring.boot.interceptor.ErrorDecoderInterceptor;
Expand Down Expand Up @@ -73,7 +62,7 @@ public class RetrofitFactoryBean<T> implements FactoryBean<T>, EnvironmentAware,
private static final Map<Class<? extends CallAdapter.Factory>, CallAdapter.Factory> CALL_ADAPTER_FACTORIES_CACHE =
new HashMap<>(4);

private Class<T> retrofitInterface;
private final Class<T> retrofitInterface;

private Environment environment;

Expand All @@ -83,7 +72,7 @@ public class RetrofitFactoryBean<T> implements FactoryBean<T>, EnvironmentAware,

private ApplicationContext applicationContext;

private RetrofitClient retrofitClient;
private final RetrofitClient retrofitClient;

private static final Map<Class<? extends Converter.Factory>, Converter.Factory> CONVERTER_FACTORIES_CACHE =
new HashMap<>(4);
Expand Down Expand Up @@ -122,40 +111,74 @@ public T getObject() throws Exception {
);
}

/**
* 加载熔断配置,熔断粒度可控制到方法级别
*/
private void loadDegradeRules() {
// 读取熔断配置
Method[] methods = retrofitInterface.getMethods();
for (Method method : methods) {
if (method.isDefault()) {
continue;
DegradeProperty degradeProperty = retrofitProperties.getDegrade();
DegradeRuleRegister degradeRuleRegister = retrofitConfigBean.getDegradeRuleRegister();

if (!degradeProperty.isEnable()) {
return;
}
Assert.notNull(degradeRuleRegister, "[DegradeRuleRegister] not found bean instance");
DegradeType degradeType = degradeProperty.getDegradeType();
switch (degradeType) {
case SENTINEL: {
Method[] methods = retrofitInterface.getMethods();
List<RetrofitDegradeRule> retrofitDegradeRuleList =
Arrays.stream(methods).map(this::convertSentinelRule).filter(Objects::nonNull).collect(Collectors.toList());
degradeRuleRegister.batchRegister(retrofitDegradeRuleList);
break;
}
int modifiers = method.getModifiers();
if (Modifier.isStatic(modifiers)) {
continue;
case RESILIENCE4J: {
break;
}
// 获取熔断配置
Degrade degrade;
if (method.isAnnotationPresent(Degrade.class)) {
degrade = method.getAnnotation(Degrade.class);
} else {
degrade = retrofitInterface.getAnnotation(Degrade.class);
default: {
throw new IllegalArgumentException("Not currently supported! degradeType=" + degradeType);
}

if (degrade == null) {
continue;
}
}

DegradeStrategy degradeStrategy = degrade.degradeStrategy();
BaseResourceNameParser resourceNameParser = retrofitConfigBean.getResourceNameParser();
String resourceName = resourceNameParser.parseResourceName(method, environment);

RetrofitDegradeRule degradeRule = new RetrofitDegradeRule();
degradeRule.setCount(degrade.count());
degradeRule.setDegradeStrategy(degradeStrategy);
degradeRule.setTimeWindow(degrade.timeWindow());
degradeRule.setResourceName(resourceName);
RetrofitDegradeRuleInitializer.addRetrofitDegradeRule(degradeRule);
}

/**
* TODO 可以优化 和{@link com.github.lianjiatech.retrofit.spring.boot.degrade.SentinelDegradeRuleRegister#convert(com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitDegradeRule)}放到一起
* Sentinel 规则转换器
* @param method method
* @return RetrofitDegradeRule
*/
private RetrofitDegradeRule convertSentinelRule(Method method) {
if (method.isDefault()) {
return null;
}
int modifiers = method.getModifiers();
if (Modifier.isStatic(modifiers)) {
return null;
}
// 获取熔断配置
Degrade degrade;
if (method.isAnnotationPresent(Degrade.class)) {
degrade = method.getAnnotation(Degrade.class);
} else {
degrade = retrofitInterface.getAnnotation(Degrade.class);
}

if (degrade == null) {
return null;
}

DegradeStrategy degradeStrategy = degrade.degradeStrategy();
BaseResourceNameParser resourceNameParser = retrofitConfigBean.getResourceNameParser();
String resourceName = resourceNameParser.parseResourceName(method, environment);

RetrofitDegradeRule degradeRule = new RetrofitDegradeRule();
degradeRule.setCount(degrade.count());
degradeRule.setDegradeStrategy(degradeStrategy);
degradeRule.setTimeWindow(degrade.timeWindow());
degradeRule.setResourceName(resourceName);
return degradeRule;
}

/**
Expand Down Expand Up @@ -284,10 +307,11 @@ private synchronized OkHttpClient getOkHttpClient(Class<?> retrofitClientInterfa
case SENTINEL: {
try {
Class.forName("com.alibaba.csp.sentinel.SphU");
SentinelDegradeInterceptor sentinelDegradeInterceptor = new SentinelDegradeInterceptor();
sentinelDegradeInterceptor.setEnvironment(environment);
sentinelDegradeInterceptor.setResourceNameParser(retrofitConfigBean.getResourceNameParser());
okHttpClientBuilder.addInterceptor(sentinelDegradeInterceptor);
DegradeInterceptor degradeInterceptor = new DegradeInterceptor();
degradeInterceptor.setEnvironment(environment);
degradeInterceptor.setResourceNameParser(retrofitConfigBean.getResourceNameParser());
degradeInterceptor.setDegradeRuleRegister(retrofitConfigBean.getDegradeRuleRegister());
okHttpClientBuilder.addInterceptor(degradeInterceptor);
} catch (ClassNotFoundException e) {
logger.warn("com.alibaba.csp.sentinel not found! No SentinelDegradeInterceptor is set.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,18 @@
/**
* @author 陈添明
*/
public abstract class BaseDegradeInterceptor implements Interceptor {
public class DegradeInterceptor implements Interceptor {

private Environment environment;

private BaseResourceNameParser resourceNameParser;

protected DegradeRuleRegister degradeRuleRegister;

public void setDegradeRuleRegister(DegradeRuleRegister degradeRuleRegister) {
this.degradeRuleRegister = degradeRuleRegister;
}

public void setEnvironment(Environment environment) {
this.environment = environment;
}
Expand Down Expand Up @@ -47,5 +53,8 @@ public Response intercept(Chain chain) throws IOException {
* @throws IOException IOException
*
*/
protected abstract Response degradeIntercept(String resourceName, Chain chain) throws RetrofitBlockException, IOException;
protected Response degradeIntercept(String resourceName, Chain chain) throws RetrofitBlockException, IOException {
Request request = chain.request();
return this.degradeRuleRegister.exec(resourceName, () -> chain.proceed(request));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.github.lianjiatech.retrofit.spring.boot.degrade;

import java.io.IOException;
import java.util.List;

/**
* @author [email protected] 2022/4/5 23:14
*/
public interface DegradeRuleRegister {

void register(RetrofitDegradeRule retrofitDegradeRule);

void batchRegister(List<RetrofitDegradeRule> retrofitDegradeRuleList);

<T> T exec(String resourceName, DegradeProxyMethod<T> func) throws IOException;

@FunctionalInterface
interface DegradeProxyMethod<R>{
R get() throws IOException;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ public enum DegradeType {

SENTINEL,

RESILIENCE4J;

}
Loading

0 comments on commit 6fe63fa

Please sign in to comment.