1
0
mirror of https://gitee.com/mirrors/Spring-Cloud-Alibaba.git synced 2021-06-26 13:25:11 +08:00

Merge pull request #486 from fangjian0423/master

Optimize CircuitBreaker in RestTemplate & update examples
This commit is contained in:
format
2019-03-27 16:29:54 +08:00
committed by GitHub
13 changed files with 163 additions and 31 deletions

View File

@@ -168,9 +168,9 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces
throws BeansException {
if (cache.containsKey(beanName)) {
// add interceptor for each RestTemplate with @SentinelRestTemplate annotation
StringBuilder interceptorBeanName = new StringBuilder();
StringBuilder interceptorBeanNamePrefix = new StringBuilder();
SentinelRestTemplate sentinelRestTemplate = cache.get(beanName);
interceptorBeanName
interceptorBeanNamePrefix
.append(StringUtils.uncapitalize(
SentinelProtectInterceptor.class.getSimpleName()))
.append("_")
@@ -179,26 +179,25 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces
.append(sentinelRestTemplate.fallbackClass().getSimpleName())
.append(sentinelRestTemplate.fallback());
RestTemplate restTemplate = (RestTemplate) bean;
registerBean(interceptorBeanName.toString(), sentinelRestTemplate);
String interceptorBeanName = interceptorBeanNamePrefix + "@"
+ bean.toString();
registerBean(interceptorBeanName, sentinelRestTemplate, (RestTemplate) bean);
SentinelProtectInterceptor sentinelProtectInterceptor = applicationContext
.getBean(interceptorBeanName.toString(),
SentinelProtectInterceptor.class);
.getBean(interceptorBeanName, SentinelProtectInterceptor.class);
restTemplate.getInterceptors().add(0, sentinelProtectInterceptor);
}
return bean;
}
private void registerBean(String interceptorBeanName,
SentinelRestTemplate sentinelRestTemplate) {
SentinelRestTemplate sentinelRestTemplate, RestTemplate restTemplate) {
// register SentinelProtectInterceptor bean
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext
.getAutowireCapableBeanFactory();
if (beanFactory.containsBean(interceptorBeanName)) {
return;
}
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
.genericBeanDefinition(SentinelProtectInterceptor.class);
beanDefinitionBuilder.addConstructorArgValue(sentinelRestTemplate);
beanDefinitionBuilder.addConstructorArgValue(restTemplate);
BeanDefinition interceptorBeanDefinition = beanDefinitionBuilder
.getRawBeanDefinition();
beanFactory.registerBeanDefinition(interceptorBeanName,

View File

@@ -27,11 +27,12 @@ import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;
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 com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
@@ -44,8 +45,12 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor
private final SentinelRestTemplate sentinelRestTemplate;
public SentinelProtectInterceptor(SentinelRestTemplate sentinelRestTemplate) {
private final RestTemplate restTemplate;
public SentinelProtectInterceptor(SentinelRestTemplate sentinelRestTemplate,
RestTemplate restTemplate) {
this.sentinelRestTemplate = sentinelRestTemplate;
this.restTemplate = restTemplate;
}
@Override
@@ -61,32 +66,33 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor
entryWithPath = false;
}
Entry hostEntry = null, hostWithPathEntry = null;
ClientHttpResponse response;
ClientHttpResponse response = null;
try {
ContextUtil.enter(hostWithPathResource);
hostEntry = SphU.entry(hostResource, EntryType.OUT);
if (entryWithPath) {
hostWithPathEntry = SphU.entry(hostWithPathResource);
hostWithPathEntry = SphU.entry(hostWithPathResource, EntryType.OUT);
}
hostEntry = SphU.entry(hostResource);
response = execution.execute(request, body);
if (this.restTemplate.getErrorHandler().hasError(response)) {
Tracer.trace(
new IllegalStateException("RestTemplate ErrorHandler has error"));
}
}
catch (Throwable e) {
if (!BlockException.isBlockException(e)) {
Tracer.trace(e);
throw new IllegalStateException(e);
}
else {
return handleBlockException(request, body, execution, (BlockException) e);
}
}
finally {
if (hostEntry != null) {
hostEntry.exit();
}
if (hostWithPathEntry != null) {
hostWithPathEntry.exit();
}
ContextUtil.exit();
if (hostEntry != null) {
hostEntry.exit();
}
}
return response;
}

View File

@@ -95,7 +95,7 @@ public class SentinelInvocationHandler implements InvocationHandler {
+ Feign.configKey(method.getDeclaringClass(), method));
// resource default is HttpMethod:protocol://url
String resourceName = methodMetadata.template().method().toUpperCase() + ":"
+ hardCodedTarget.url() + methodMetadata.template().url();
+ hardCodedTarget.url() + methodMetadata.template().path();
Entry entry = null;
try {
ContextUtil.enter(resourceName);
@@ -128,7 +128,7 @@ public class SentinelInvocationHandler implements InvocationHandler {
}
finally {
if (entry != null) {
entry.exit();
entry.exit(1, args);
}
ContextUtil.exit();
}

View File

@@ -106,14 +106,16 @@ public class SentinelAutoConfigurationTests {
@LocalServerPort
private int port;
private String url = "http://localhost:" + port;
private String flowUrl = "http://localhost:" + port + "/flow";
private String degradeUrl = "http://localhost:" + port + "/degrade";
@Before
public void setUp() {
FlowRule rule = new FlowRule();
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(0);
rule.setResource("GET:" + url);
rule.setResource("GET:" + flowUrl);
rule.setLimitApp("default");
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
rule.setStrategy(RuleConstant.STRATEGY_DIRECT);
@@ -121,7 +123,7 @@ public class SentinelAutoConfigurationTests {
DegradeRule degradeRule = new DegradeRule();
degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
degradeRule.setResource("GET:" + url + "/test");
degradeRule.setResource("GET:" + degradeUrl);
degradeRule.setCount(0);
degradeRule.setTimeWindow(60);
DegradeRuleManager.loadRules(Arrays.asList(degradeRule));
@@ -247,14 +249,15 @@ public class SentinelAutoConfigurationTests {
restTemplate.getInterceptors().size());
assertEquals("RestTemplateWithBlockClass interceptors size was wrong", 1,
restTemplateWithBlockClass.getInterceptors().size());
ResponseEntity responseEntityBlock = restTemplateWithBlockClass.getForEntity(url,
String.class);
ResponseEntity responseEntityBlock = restTemplateWithBlockClass
.getForEntity(flowUrl, String.class);
assertEquals("RestTemplateWithBlockClass Sentinel Block Message was wrong",
"Oops", responseEntityBlock.getBody());
assertEquals(
"RestTemplateWithBlockClass Sentinel Block Http Status Code was wrong",
HttpStatus.OK, responseEntityBlock.getStatusCode());
ResponseEntity responseEntityRaw = restTemplate.getForEntity(url, String.class);
ResponseEntity responseEntityRaw = restTemplate.getForEntity(flowUrl,
String.class);
assertEquals("RestTemplate Sentinel Block Message was wrong",
"RestTemplate request block by sentinel", responseEntityRaw.getBody());
assertEquals("RestTemplate Sentinel Block Http Status Code was wrong",
@@ -266,14 +269,14 @@ public class SentinelAutoConfigurationTests {
assertEquals("RestTemplateWithoutBlockClass interceptors size was wrong", 0,
restTemplateWithoutBlockClass.getInterceptors().size());
assertThatExceptionOfType(RestClientException.class).isThrownBy(() -> {
restTemplateWithoutBlockClass.getForEntity(url, String.class);
restTemplateWithoutBlockClass.getForEntity(flowUrl, String.class);
});
}
@Test
public void testFallbackRestTemplate() {
ResponseEntity responseEntity = restTemplateWithFallbackClass
.getForEntity(url + "/test", String.class);
.getForEntity(degradeUrl, String.class);
assertEquals("RestTemplateWithFallbackClass Sentinel Message was wrong",
"Oops fallback", responseEntity.getBody());
assertEquals("RestTemplateWithFallbackClass Sentinel Http Status Code was wrong",