From 526f9d4f27292a0d5f139f84a943e94799e7982a Mon Sep 17 00:00:00 2001 From: seanyu Date: Sat, 18 Mar 2023 00:19:03 +0800 Subject: [PATCH] support resttemplate default fallback --- ...olarisCircuitBreakerAutoConfiguration.java | 8 ---- ...sCircuitBreakerBootstrapConfiguration.java | 8 +++- ...tBreakerRestTemplateAutoConfiguration.java | 24 +++++++++++ ...olarisCircuitBreakerAutoConfiguration.java | 2 +- .../PolarisCircuitBreakerHttpResponse.java | 8 ++-- .../PolarisCircuitBreakerRestTemplate.java | 2 +- ...tBreakerRestTemplateBeanPostProcessor.java | 24 ++++++----- ...CircuitBreakerRestTemplateInterceptor.java | 6 +-- .../main/resources/META-INF/spring.factories | 3 +- .../example/ServiceBController.java | 12 ++++++ .../example/ServiceBController.java | 16 ++++++++ .../CustomPolarisCircuitBreakerFallback.java | 17 ++++++++ .../example/ServiceAController.java | 40 +++++++++++++------ .../example/ServiceAResTemplate.java | 25 +++++++++++- .../EnhancedRestTemplateReporter.java | 4 ++ 15 files changed, 159 insertions(+), 40 deletions(-) create mode 100644 spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerRestTemplateAutoConfiguration.java create mode 100644 spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/example/CustomPolarisCircuitBreakerFallback.java diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerAutoConfiguration.java index b6f3b4c89..3005ac672 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerAutoConfiguration.java @@ -76,12 +76,4 @@ public class PolarisCircuitBreakerAutoConfiguration { return new CircuitBreakerConfigModifier(properties); } - @Bean - @ConditionalOnMissingBean - @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") - public static PolarisCircuitBreakerRestTemplateBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext, CircuitBreakerFactory circuitBreakerFactory) { - return new PolarisCircuitBreakerRestTemplateBeanPostProcessor(applicationContext, circuitBreakerFactory); - } - } diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerBootstrapConfiguration.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerBootstrapConfiguration.java index c1cafea0b..449c09176 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerBootstrapConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerBootstrapConfiguration.java @@ -28,7 +28,13 @@ import org.springframework.context.annotation.Import; */ @Configuration(proxyBeanMethods = false) @ConditionalOnProperty("spring.cloud.polaris.enabled") -@Import({PolarisCircuitBreakerAutoConfiguration.class, ReactivePolarisCircuitBreakerAutoConfiguration.class, PolarisCircuitBreakerFeignClientAutoConfiguration.class}) +@Import({ + PolarisCircuitBreakerAutoConfiguration.class, + ReactivePolarisCircuitBreakerAutoConfiguration.class, + PolarisCircuitBreakerFeignClientAutoConfiguration.class, + GatewayPolarisCircuitBreakerAutoConfiguration.class, + PolarisCircuitBreakerRestTemplateAutoConfiguration.class +}) public class PolarisCircuitBreakerBootstrapConfiguration { } diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerRestTemplateAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerRestTemplateAutoConfiguration.java new file mode 100644 index 000000000..a9efc3d6e --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerRestTemplateAutoConfiguration.java @@ -0,0 +1,24 @@ +package com.tencent.cloud.polaris.circuitbreaker.config; + +import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreakerRestTemplateBeanPostProcessor; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration(proxyBeanMethods = false) +@ConditionalOnPolarisCircuitBreakerEnabled +@AutoConfigureAfter(PolarisCircuitBreakerAutoConfiguration.class) +public class PolarisCircuitBreakerRestTemplateAutoConfiguration { + + @Bean + @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") + public static PolarisCircuitBreakerRestTemplateBeanPostProcessor polarisCircuitBreakerRestTemplateBeanPostProcessor( + ApplicationContext applicationContext) { + return new PolarisCircuitBreakerRestTemplateBeanPostProcessor(applicationContext); + } + +} diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/ReactivePolarisCircuitBreakerAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/ReactivePolarisCircuitBreakerAutoConfiguration.java index 58ca348a5..9d9bf911e 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/ReactivePolarisCircuitBreakerAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/ReactivePolarisCircuitBreakerAutoConfiguration.java @@ -60,7 +60,7 @@ public class ReactivePolarisCircuitBreakerAutoConfiguration { @Bean @ConditionalOnMissingBean(ReactiveCircuitBreakerFactory.class) - public ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory(CircuitBreakAPI circuitBreakAPI) { + public ReactiveCircuitBreakerFactory polarisReactiveCircuitBreakerFactory(CircuitBreakAPI circuitBreakAPI) { ReactivePolarisCircuitBreakerFactory factory = new ReactivePolarisCircuitBreakerFactory(circuitBreakAPI); customizers.forEach(customizer -> customizer.customize(factory)); return factory; diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerHttpResponse.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerHttpResponse.java index 67e868e31..24686ce86 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerHttpResponse.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerHttpResponse.java @@ -11,6 +11,8 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.client.AbstractClientHttpResponse; +import static com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateReporter.POLARIS_CIRCUIT_BREAKER_FALLBACK_HEADER; + public class PolarisCircuitBreakerHttpResponse extends AbstractClientHttpResponse { private final CircuitBreakerStatus.FallbackInfo fallbackInfo; @@ -57,12 +59,12 @@ public class PolarisCircuitBreakerHttpResponse extends AbstractClientHttpRespons @Override public HttpHeaders getHeaders() { + HttpHeaders headers = new HttpHeaders(); if (fallbackInfo.getHeaders() != null) { - HttpHeaders headers = new HttpHeaders(); fallbackInfo.getHeaders().forEach(headers::add); - return headers; } - return null; + headers.add(POLARIS_CIRCUIT_BREAKER_FALLBACK_HEADER, "true"); + return headers; } } diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplate.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplate.java index 9d98b98c2..0e07148b9 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplate.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplate.java @@ -13,6 +13,6 @@ public @interface PolarisCircuitBreakerRestTemplate { String fallback() default ""; - Class fallbackClass() default PolarisCircuitBreakerFallback.class; + Class fallbackClass() default PolarisCircuitBreakerFallback.class; } diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateBeanPostProcessor.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateBeanPostProcessor.java index 315ebfb9b..1269797d6 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateBeanPostProcessor.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateBeanPostProcessor.java @@ -2,6 +2,9 @@ package com.tencent.cloud.polaris.circuitbreaker.resttemplate; import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; @@ -17,20 +20,22 @@ import org.springframework.web.client.RestTemplate; public class PolarisCircuitBreakerRestTemplateBeanPostProcessor implements MergedBeanDefinitionPostProcessor { + private static final Logger log = LoggerFactory.getLogger(PolarisCircuitBreakerRestTemplateBeanPostProcessor.class); private final ApplicationContext applicationContext; - private final CircuitBreakerFactory circuitBreakerFactory; - - public PolarisCircuitBreakerRestTemplateBeanPostProcessor(ApplicationContext applicationContext, CircuitBreakerFactory circuitBreakerFactory) { + public PolarisCircuitBreakerRestTemplateBeanPostProcessor(ApplicationContext applicationContext) { this.applicationContext = applicationContext; - this.circuitBreakerFactory = circuitBreakerFactory; } - private ConcurrentHashMap cache = new ConcurrentHashMap<>(); - - private void checkPolarisCircuitBreakerRestTemplate(PolarisCircuitBreakerRestTemplate polarisCircuitBreakerRestTemplate, - String beanName) { + private final ConcurrentHashMap cache = new ConcurrentHashMap<>(); + private void checkPolarisCircuitBreakerRestTemplate(PolarisCircuitBreakerRestTemplate polarisCircuitBreakerRestTemplate) { + if ( + StringUtils.hasText(polarisCircuitBreakerRestTemplate.fallback()) && + !PolarisCircuitBreakerFallback.class.toGenericString().equals(polarisCircuitBreakerRestTemplate.fallbackClass().toGenericString()) + ) { + throw new IllegalArgumentException("PolarisCircuitBreakerRestTemplate's fallback and fallbackClass could not set at sametime !"); + } } @Override @@ -45,7 +50,7 @@ public class PolarisCircuitBreakerRestTemplateBeanPostProcessor implements Merge polarisCircuitBreakerRestTemplate = beanDefinition.getResolvedFactoryMethod() .getAnnotation(PolarisCircuitBreakerRestTemplate.class); } - checkPolarisCircuitBreakerRestTemplate(polarisCircuitBreakerRestTemplate, beanName); + checkPolarisCircuitBreakerRestTemplate(polarisCircuitBreakerRestTemplate); cache.put(beanName, polarisCircuitBreakerRestTemplate); } } @@ -63,6 +68,7 @@ public class PolarisCircuitBreakerRestTemplateBeanPostProcessor implements Merge .append(polarisCircuitBreakerRestTemplate.fallbackClass().getSimpleName()); RestTemplate restTemplate = (RestTemplate) bean; String interceptorBeanName = interceptorBeanNamePrefix + "@" + bean; + CircuitBreakerFactory circuitBreakerFactory = this.applicationContext.getBean(CircuitBreakerFactory.class); registerBean(interceptorBeanName, polarisCircuitBreakerRestTemplate, applicationContext, circuitBreakerFactory); PolarisCircuitBreakerRestTemplateInterceptor polarisCircuitBreakerRestTemplateInterceptor = applicationContext .getBean(interceptorBeanName, PolarisCircuitBreakerRestTemplateInterceptor.class); diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateInterceptor.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateInterceptor.java index 204b28c90..a8baf81ab 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateInterceptor.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateInterceptor.java @@ -5,7 +5,6 @@ import java.lang.reflect.Method; import com.tencent.polaris.api.pojo.CircuitBreakerStatus; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; -import org.apache.commons.lang.StringUtils; import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory; import org.springframework.context.ApplicationContext; @@ -14,6 +13,7 @@ import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; public class PolarisCircuitBreakerRestTemplateInterceptor implements ClientHttpRequestInterceptor { @@ -45,11 +45,11 @@ public class PolarisCircuitBreakerRestTemplateInterceptor implements ClientHttpR } }, t -> { - if (!StringUtils.isEmpty(polarisCircuitBreakerRestTemplate.fallback())) { + if (StringUtils.hasText(polarisCircuitBreakerRestTemplate.fallback())) { CircuitBreakerStatus.FallbackInfo fallbackInfo = new CircuitBreakerStatus.FallbackInfo(200, null, polarisCircuitBreakerRestTemplate.fallback()); return new PolarisCircuitBreakerHttpResponse(fallbackInfo); } - if (polarisCircuitBreakerRestTemplate.fallbackClass() != null && polarisCircuitBreakerRestTemplate.fallbackClass().getSuperclass() != null) { + if (!PolarisCircuitBreakerFallback.class.toGenericString().equals(polarisCircuitBreakerRestTemplate.fallbackClass().toGenericString())) { Method method = ReflectionUtils.findMethod(PolarisCircuitBreakerFallback.class, "fallback"); PolarisCircuitBreakerFallback polarisCircuitBreakerFallback = applicationContext.getBean(polarisCircuitBreakerRestTemplate.fallbackClass()); return (PolarisCircuitBreakerHttpResponse) ReflectionUtils.invokeMethod(method, polarisCircuitBreakerFallback); diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/resources/META-INF/spring.factories b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/resources/META-INF/spring.factories index a873ed563..2d5176713 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/resources/META-INF/spring.factories @@ -2,6 +2,7 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerAutoConfiguration,\ com.tencent.cloud.polaris.circuitbreaker.config.ReactivePolarisCircuitBreakerAutoConfiguration,\ com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerFeignClientAutoConfiguration,\ - com.tencent.cloud.polaris.circuitbreaker.config.GatewayPolarisCircuitBreakerAutoConfiguration + com.tencent.cloud.polaris.circuitbreaker.config.GatewayPolarisCircuitBreakerAutoConfiguration,\ + com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerRestTemplateAutoConfiguration org.springframework.cloud.bootstrap.BootstrapConfiguration=\ com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerBootstrapConfiguration diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-callee-service/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/ServiceBController.java b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-callee-service/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/ServiceBController.java index 128ea5e4d..8628db06a 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-callee-service/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/ServiceBController.java +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-callee-service/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/ServiceBController.java @@ -40,4 +40,16 @@ public class ServiceBController { public String info() { return "hello world ! I'm a service B1"; } + + @GetMapping("/health") + public String health() { + System.out.println("health check: 200 instance"); + return "hello world ! I'm a service B1"; + } + + @GetMapping("/health-svc") + public String healthsvc() { + System.out.println("health-svc check: 200 instance"); + return "hello world ! I'm a service B1"; + } } diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-callee-service2/src/main/java/com/tencent/cloud/polaris/ciruitbreaker/example/ServiceBController.java b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-callee-service2/src/main/java/com/tencent/cloud/polaris/ciruitbreaker/example/ServiceBController.java index 384167816..8b8ceb557 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-callee-service2/src/main/java/com/tencent/cloud/polaris/ciruitbreaker/example/ServiceBController.java +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-callee-service2/src/main/java/com/tencent/cloud/polaris/ciruitbreaker/example/ServiceBController.java @@ -18,6 +18,8 @@ package com.tencent.cloud.polaris.ciruitbreaker.example; +import java.util.concurrent.atomic.AtomicInteger; + import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -43,4 +45,18 @@ public class ServiceBController { public String info() { return "failed for call service B2"; } + + @GetMapping("/health") + @ResponseStatus(value = HttpStatus.BAD_GATEWAY, reason = "failed for call my service") + public String health() { + System.out.println("health check: 502 instance"); + return "hello world ! I'm a service B1"; + } + + @GetMapping("/health-svc") + @ResponseStatus(value = HttpStatus.BAD_GATEWAY, reason = "failed for call my service") + public String healthsvc() { + System.out.println("health-svc check: 502 instance"); + return "hello world ! I'm a service B1"; + } } diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/example/CustomPolarisCircuitBreakerFallback.java b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/example/CustomPolarisCircuitBreakerFallback.java new file mode 100644 index 000000000..a845cf3e4 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/example/CustomPolarisCircuitBreakerFallback.java @@ -0,0 +1,17 @@ +package com.tencent.cloud.polaris.circuitbreaker.resttemplate.example; + + +import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreakerFallback; +import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreakerHttpResponse; + +import org.springframework.stereotype.Component; + +@Component +public class CustomPolarisCircuitBreakerFallback implements PolarisCircuitBreakerFallback { + @Override + public PolarisCircuitBreakerHttpResponse fallback() { + return new PolarisCircuitBreakerHttpResponse( + 200, + "{\"msg\": \"this is a fallback class\"}"); + } +} diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/example/ServiceAController.java b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/example/ServiceAController.java index 6c50b5252..39fcc5d35 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/example/ServiceAController.java +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/example/ServiceAController.java @@ -19,7 +19,9 @@ package com.tencent.cloud.polaris.circuitbreaker.resttemplate.example; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -35,24 +37,38 @@ import org.springframework.web.client.RestTemplate; public class ServiceAController { @Autowired - private RestTemplate restTemplate; + @Qualifier("defaultRestTemplate") + private RestTemplate defaultRestTemplate; @Autowired - private CircuitBreakerFactory circuitBreakerFactory; + @Qualifier("fallbackRestTemplate") + private RestTemplate fallbackRestTemplate; + + @Autowired + @Qualifier("fallbackClassRestTemplate") + private RestTemplate fallbackClassRestTemplate; -// @GetMapping("/getBServiceInfo") -// public String getBServiceInfo() { -// return circuitBreakerFactory -// .create("polaris-circuitbreaker-callee-service#/example/service/b/info") -// .run(() -> -// restTemplate.getForObject("/example/service/b/info", String.class), -// throwable -> "trigger the refuse for service b" -// ); -// } + @Autowired + private CircuitBreakerFactory circuitBreakerFactory; @GetMapping("/getBServiceInfo") public String getBServiceInfo() { - return restTemplate.getForObject("/example/service/b/info", String.class); + return circuitBreakerFactory + .create("polaris-circuitbreaker-callee-service#/example/service/b/info") + .run(() -> + defaultRestTemplate.getForObject("/example/service/b/info", String.class), + throwable -> "trigger the refuse for service b" + ); + } + + @GetMapping("/getBServiceInfo/fallback") + public String getBServiceInfoFallback() { + return fallbackRestTemplate.getForObject("/example/service/b/info", String.class); + } + + @GetMapping("/getBServiceInfo/fallbackClass") + public String getBServiceInfoFallbackClass() { + return fallbackClassRestTemplate.getForObject("/example/service/b/info", String.class); } } diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/example/ServiceAResTemplate.java b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/example/ServiceAResTemplate.java index ed40e9424..c0340cc40 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/example/ServiceAResTemplate.java +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/example/ServiceAResTemplate.java @@ -20,10 +20,14 @@ package com.tencent.cloud.polaris.circuitbreaker.resttemplate.example; import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreakerFallback; import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreakerRestTemplate; +import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreakerRestTemplateBeanPostProcessor; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriBuilderFactory; @@ -40,10 +44,29 @@ public class ServiceAResTemplate { SpringApplication.run(ServiceAResTemplate.class, args); } + @Bean + @LoadBalanced + public RestTemplate defaultRestTemplate() { + DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://polaris-circuitbreaker-callee-service"); + RestTemplate restTemplate = new RestTemplate(); + restTemplate.setUriTemplateHandler(uriBuilderFactory); + return restTemplate; + } + @Bean @LoadBalanced @PolarisCircuitBreakerRestTemplate - public RestTemplate restTemplate() { + public RestTemplate fallbackRestTemplate() { + DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://polaris-circuitbreaker-callee-service"); + RestTemplate restTemplate = new RestTemplate(); + restTemplate.setUriTemplateHandler(uriBuilderFactory); + return restTemplate; + } + + @Bean + @LoadBalanced + @PolarisCircuitBreakerRestTemplate(fallbackClass = CustomPolarisCircuitBreakerFallback.class) + public RestTemplate fallbackClassRestTemplate() { DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://polaris-circuitbreaker-callee-service"); RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(uriBuilderFactory); diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateReporter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateReporter.java index b8f842e77..8cf16e1a9 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateReporter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateReporter.java @@ -56,6 +56,7 @@ import static com.tencent.cloud.common.constant.ContextConstant.UTF_8; */ public class EnhancedRestTemplateReporter extends AbstractPolarisReporterAdapter implements ResponseErrorHandler, ApplicationContextAware { + public static final String POLARIS_CIRCUIT_BREAKER_FALLBACK_HEADER = "PolarisCircuitBreakerFallback"; static final String HEADER_HAS_ERROR = "X-SCT-Has-Error"; private static final Logger LOGGER = LoggerFactory.getLogger(EnhancedRestTemplateReporter.class); private final ConsumerAPI consumerAPI; @@ -117,6 +118,9 @@ public class EnhancedRestTemplateReporter extends AbstractPolarisReporterAdapter } private void reportResult(URI url, ClientHttpResponse response) { + if (Boolean.parseBoolean(response.getHeaders().getFirst(POLARIS_CIRCUIT_BREAKER_FALLBACK_HEADER))){ + return; + } ServiceCallResult resultRequest = createServiceCallResult(url); try { Map loadBalancerContext = MetadataContextHolder.get().getLoadbalancerMetadata();