add scg circuit breaker support

pull/881/head
seanyu 3 years ago
parent a45c07eb29
commit 2afc913fc1

@ -55,6 +55,30 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<optional>true</optional>
</dependency>
<!-- Polaris dependencies end --> <!-- Polaris dependencies end -->
<dependency> <dependency>

@ -20,6 +20,7 @@ package com.tencent.cloud.polaris.circuitbreaker;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.tencent.cloud.polaris.circuitbreaker.common.PolarisResultToErrorCode;
import com.tencent.polaris.api.pojo.ServiceKey; import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.api.FunctionalDecorator; import com.tencent.polaris.circuitbreak.api.FunctionalDecorator;
@ -31,7 +32,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.circuitbreaker.CircuitBreaker; import org.springframework.cloud.client.circuitbreaker.CircuitBreaker;
/** /**
* PolarisCircuitBreaker * PolarisCircuitBreaker.
* *
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */
@ -44,6 +45,7 @@ public class PolarisCircuitBreaker implements CircuitBreaker {
public PolarisCircuitBreaker(String sourceNamespace, String sourceService, String namespace, String service, String method, CircuitBreakAPI circuitBreakAPI) { public PolarisCircuitBreaker(String sourceNamespace, String sourceService, String namespace, String service, String method, CircuitBreakAPI circuitBreakAPI) {
FunctionalDecoratorRequest makeDecoratorRequest = new FunctionalDecoratorRequest(new ServiceKey(namespace, service), method); FunctionalDecoratorRequest makeDecoratorRequest = new FunctionalDecoratorRequest(new ServiceKey(namespace, service), method);
makeDecoratorRequest.setSourceService(new ServiceKey(sourceNamespace, sourceService)); makeDecoratorRequest.setSourceService(new ServiceKey(sourceNamespace, sourceService));
makeDecoratorRequest.setResultToErrorCode(new PolarisResultToErrorCode());
this.decorator = circuitBreakAPI.makeFunctionalDecorator(makeDecoratorRequest); this.decorator = circuitBreakAPI.makeFunctionalDecorator(makeDecoratorRequest);
} }

@ -19,13 +19,15 @@ package com.tencent.cloud.polaris.circuitbreaker;
import java.util.function.Function; import java.util.function.Function;
import com.tencent.cloud.polaris.circuitbreaker.common.PolarisCircuitBreakerConfigBuilder;
import com.tencent.cloud.polaris.circuitbreaker.util.PolarisCircuitBreakerUtils;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import org.springframework.cloud.client.circuitbreaker.CircuitBreaker; import org.springframework.cloud.client.circuitbreaker.CircuitBreaker;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory; import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
/** /**
* PolarisCircuitBreakerFactory * PolarisCircuitBreakerFactory.
* *
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */

@ -19,20 +19,20 @@ package com.tencent.cloud.polaris.circuitbreaker;
import java.util.function.Function; import java.util.function.Function;
import com.tencent.cloud.polaris.circuitbreaker.common.PolarisResultToErrorCode;
import com.tencent.cloud.polaris.circuitbreaker.reactor.PolarisCircuitBreakerReactorTransformer; import com.tencent.cloud.polaris.circuitbreaker.reactor.PolarisCircuitBreakerReactorTransformer;
import com.tencent.polaris.api.pojo.ServiceKey; import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.api.InvokeHandler; import com.tencent.polaris.circuitbreak.api.InvokeHandler;
import com.tencent.polaris.circuitbreak.api.pojo.FunctionalDecoratorRequest; import com.tencent.polaris.circuitbreak.api.pojo.FunctionalDecoratorRequest;
import com.tencent.polaris.circuitbreak.api.pojo.InvokeContext; import com.tencent.polaris.circuitbreak.api.pojo.InvokeContext;
import com.tencent.polaris.circuitbreak.client.api.DefaultInvokeHandler;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreaker; import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreaker;
/** /**
* ReactivePolarisCircuitBreaker * ReactivePolarisCircuitBreaker.
* *
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */
@ -43,6 +43,7 @@ public class ReactivePolarisCircuitBreaker implements ReactiveCircuitBreaker {
public ReactivePolarisCircuitBreaker(String sourceNamespace, String sourceService, String namespace, String service, String method, CircuitBreakAPI circuitBreakAPI) { public ReactivePolarisCircuitBreaker(String sourceNamespace, String sourceService, String namespace, String service, String method, CircuitBreakAPI circuitBreakAPI) {
InvokeContext.RequestContext requestContext = new FunctionalDecoratorRequest(new ServiceKey(namespace, service), method); InvokeContext.RequestContext requestContext = new FunctionalDecoratorRequest(new ServiceKey(namespace, service), method);
requestContext.setSourceService(new ServiceKey(sourceNamespace, sourceService)); requestContext.setSourceService(new ServiceKey(sourceNamespace, sourceService));
requestContext.setResultToErrorCode(new PolarisResultToErrorCode());
this.invokeHandler = circuitBreakAPI.makeInvokeHandler(requestContext); this.invokeHandler = circuitBreakAPI.makeInvokeHandler(requestContext);
} }

@ -19,13 +19,15 @@ package com.tencent.cloud.polaris.circuitbreaker;
import java.util.function.Function; import java.util.function.Function;
import com.tencent.cloud.polaris.circuitbreaker.common.PolarisCircuitBreakerConfigBuilder;
import com.tencent.cloud.polaris.circuitbreaker.util.PolarisCircuitBreakerUtils;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreaker; import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreaker;
import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory; import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;
/** /**
* ReactivePolarisCircuitBreakerFactory * ReactivePolarisCircuitBreakerFactory.
* *
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */

@ -0,0 +1,62 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.circuitbreaker.common;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.config.consumer.ServiceRouterConfig;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import com.tencent.polaris.plugins.router.healthy.RecoverRouterConfig;
/**
* CircuitBreakerConfigModifier.
*
* @author seanyu 2023-02-27
*/
public class CircuitBreakerConfigModifier implements PolarisConfigModifier {
private final RpcEnhancementReporterProperties properties;
public CircuitBreakerConfigModifier(RpcEnhancementReporterProperties properties) {
this.properties = properties;
}
@Override
public void modify(ConfigurationImpl configuration) {
properties.setEnabled(true);
// Turn on circuitbreaker configuration
configuration.getConsumer().getCircuitBreaker().setEnable(true);
// Set excludeCircuitBreakInstances to true
RecoverRouterConfig recoverRouterConfig = configuration.getConsumer().getServiceRouter()
.getPluginConfig(ServiceRouterConfig.DEFAULT_ROUTER_RECOVER, RecoverRouterConfig.class);
recoverRouterConfig.setExcludeCircuitBreakInstances(true);
// Update modified config to source properties
configuration.getConsumer().getServiceRouter()
.setPluginConfig(ServiceRouterConfig.DEFAULT_ROUTER_RECOVER, recoverRouterConfig);
}
@Override
public int getOrder() {
return ContextConstant.ModifierOrder.CIRCUIT_BREAKER_ORDER;
}
}

@ -15,14 +15,14 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.circuitbreaker; package com.tencent.cloud.polaris.circuitbreaker.common;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import org.springframework.cloud.client.circuitbreaker.ConfigBuilder; import org.springframework.cloud.client.circuitbreaker.ConfigBuilder;
/** /**
* PolarisCircuitBreakerConfigBuilder * PolarisCircuitBreakerConfigBuilder.
* *
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */

@ -0,0 +1,65 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.circuitbreaker.common;
import com.tencent.polaris.circuitbreak.api.pojo.ResultToErrorCode;
import feign.FeignException;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.reactive.function.client.WebClientResponseException;
/**
* PolarisResultToErrorCode.
*
* @author seanyu 2023-02-27
*/
public class PolarisResultToErrorCode implements ResultToErrorCode {
@Override
public int onSuccess(Object value) {
return 200;
}
@Override
public int onError(Throwable e) {
if (checkClassExist("org.springframework.web.client.RestClientResponseException")
&& e instanceof RestClientResponseException) {
return ((RestClientResponseException) e).getRawStatusCode();
}
else if (checkClassExist("feign.FeignException")
&& e instanceof FeignException) {
return ((FeignException) e).status();
}
else if (checkClassExist("org.springframework.web.reactive.function.client.WebClientResponseException")
&& e instanceof WebClientResponseException) {
return ((WebClientResponseException) e).getRawStatusCode();
}
return -1;
}
private boolean checkClassExist(String clazzName) {
try {
Class.forName(clazzName, false, getClass().getClassLoader());
}
catch (ClassNotFoundException e) {
return false;
}
return true;
}
}

@ -0,0 +1,66 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.circuitbreaker.config;
import com.tencent.cloud.polaris.circuitbreaker.ReactivePolarisCircuitBreakerFactory;
import com.tencent.cloud.polaris.circuitbreaker.gateway.PolarisCircuitBreakerFilterFactory;
import org.springframework.beans.factory.ObjectProvider;
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.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;
import org.springframework.cloud.gateway.config.GatewayAutoConfiguration;
import org.springframework.cloud.gateway.config.conditional.ConditionalOnEnabledFilter;
import org.springframework.cloud.gateway.filter.factory.FallbackHeadersGatewayFilterFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.DispatcherHandler;
/**
* GatewayPolarisCircuitBreakerAutoConfiguration.
*
* @author seanyu 2023-02-27
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@AutoConfigureAfter({ReactivePolarisCircuitBreakerAutoConfiguration.class })
@ConditionalOnClass({ DispatcherHandler.class, ReactivePolarisCircuitBreakerAutoConfiguration.class,
ReactiveCircuitBreakerFactory.class, ReactivePolarisCircuitBreakerFactory.class, GatewayAutoConfiguration.class})
public class GatewayPolarisCircuitBreakerAutoConfiguration {
@Bean
@ConditionalOnBean(ReactivePolarisCircuitBreakerFactory.class)
@ConditionalOnEnabledFilter
public PolarisCircuitBreakerFilterFactory polarisCircuitBreakerFilterFactory(
ReactivePolarisCircuitBreakerFactory reactiveCircuitBreakerFactory,
ObjectProvider<DispatcherHandler> dispatcherHandler
) {
return new PolarisCircuitBreakerFilterFactory(reactiveCircuitBreakerFactory, dispatcherHandler);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledFilter
public FallbackHeadersGatewayFilterFactory fallbackHeadersGatewayFilterFactory() {
return new FallbackHeadersGatewayFilterFactory();
}
}

@ -20,24 +20,18 @@ package com.tencent.cloud.polaris.circuitbreaker.config;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.polaris.circuitbreaker.PolarisCircuitBreakerFactory; import com.tencent.cloud.polaris.circuitbreaker.PolarisCircuitBreakerFactory;
import com.tencent.cloud.polaris.context.PolarisConfigModifier; import com.tencent.cloud.polaris.circuitbreaker.common.CircuitBreakerConfigModifier;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.config.consumer.ServiceRouterConfig;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.factory.CircuitBreakAPIFactory; import com.tencent.polaris.circuitbreak.factory.CircuitBreakAPIFactory;
import com.tencent.polaris.client.api.SDKContext; import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import com.tencent.polaris.plugins.router.healthy.RecoverRouterConfig;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 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.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory; import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.cloud.client.circuitbreaker.Customizer; import org.springframework.cloud.client.circuitbreaker.Customizer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -45,7 +39,7 @@ import org.springframework.context.annotation.Configuration;
/** /**
* Autoconfiguration for PolarisCircuitBreaker * Autoconfiguration for PolarisCircuitBreaker.
* *
* @author lepdou 2022-03-29 * @author lepdou 2022-03-29
*/ */
@ -73,40 +67,9 @@ public class PolarisCircuitBreakerAutoConfiguration {
@Bean @Bean
@ConditionalOnBean(RpcEnhancementReporterProperties.class) @ConditionalOnBean(RpcEnhancementReporterProperties.class)
@ConditionalOnMissingBean(CircuitBreakerConfigModifier.class)
public CircuitBreakerConfigModifier circuitBreakerConfigModifier(RpcEnhancementReporterProperties properties) { public CircuitBreakerConfigModifier circuitBreakerConfigModifier(RpcEnhancementReporterProperties properties) {
return new CircuitBreakerConfigModifier(properties); return new CircuitBreakerConfigModifier(properties);
} }
public static class CircuitBreakerConfigModifier implements PolarisConfigModifier {
private final RpcEnhancementReporterProperties properties;
public CircuitBreakerConfigModifier(RpcEnhancementReporterProperties properties) {
this.properties = properties;
}
@Override
public void modify(ConfigurationImpl configuration) {
properties.setEnabled(true);
// Turn on circuitbreaker configuration
configuration.getConsumer().getCircuitBreaker().setEnable(true);
// Set excludeCircuitBreakInstances to true
RecoverRouterConfig recoverRouterConfig = configuration.getConsumer().getServiceRouter()
.getPluginConfig(ServiceRouterConfig.DEFAULT_ROUTER_RECOVER, RecoverRouterConfig.class);
recoverRouterConfig.setExcludeCircuitBreakInstances(true);
// Update modified config to source properties
configuration.getConsumer().getServiceRouter()
.setPluginConfig(ServiceRouterConfig.DEFAULT_ROUTER_RECOVER, recoverRouterConfig);
}
@Override
public int getOrder() {
return ContextConstant.ModifierOrder.CIRCUIT_BREAKER_ORDER;
}
}
} }

@ -28,7 +28,7 @@ import org.springframework.context.annotation.Import;
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnProperty("spring.cloud.polaris.enabled") @ConditionalOnProperty("spring.cloud.polaris.enabled")
@Import({PolarisCircuitBreakerAutoConfiguration.class, ReactivePolarisCircuitBreakerAutoConfiguration.class}) @Import({PolarisCircuitBreakerAutoConfiguration.class, ReactivePolarisCircuitBreakerAutoConfiguration.class, PolarisCircuitBreakerFeignClientAutoConfiguration.class})
public class PolarisCircuitBreakerBootstrapConfiguration { public class PolarisCircuitBreakerBootstrapConfiguration {
} }

@ -0,0 +1,24 @@
package com.tencent.cloud.polaris.circuitbreaker.config;
import com.tencent.cloud.polaris.circuitbreaker.feign.PolarisCircuitBreakerNameResolver;
import feign.Feign;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.openfeign.CircuitBreakerNameResolver;
import org.springframework.cloud.openfeign.FeignClientFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Feign.class, FeignClientFactoryBean.class })
@ConditionalOnPolarisCircuitBreakerEnabled
public class PolarisCircuitBreakerFeignClientAutoConfiguration {
@Bean
@ConditionalOnMissingBean(CircuitBreakerNameResolver.class)
public CircuitBreakerNameResolver polarisCircuitBreakerNameResolver() {
return new PolarisCircuitBreakerNameResolver();
}
}

@ -20,31 +20,26 @@ package com.tencent.cloud.polaris.circuitbreaker.config;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.polaris.circuitbreaker.ReactivePolarisCircuitBreakerFactory; import com.tencent.cloud.polaris.circuitbreaker.ReactivePolarisCircuitBreakerFactory;
import com.tencent.cloud.polaris.context.PolarisConfigModifier; import com.tencent.cloud.polaris.circuitbreaker.common.CircuitBreakerConfigModifier;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.config.consumer.ServiceRouterConfig;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.factory.CircuitBreakAPIFactory; import com.tencent.polaris.circuitbreak.factory.CircuitBreakAPIFactory;
import com.tencent.polaris.client.api.SDKContext; import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import com.tencent.polaris.plugins.router.healthy.RecoverRouterConfig;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.circuitbreaker.Customizer; import org.springframework.cloud.client.circuitbreaker.Customizer;
import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory; import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
/** /**
* AutoConfiguration for ReactivePolarisCircuitBreaker * AutoConfiguration for ReactivePolarisCircuitBreaker.
* *
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */
@ -73,40 +68,9 @@ public class ReactivePolarisCircuitBreakerAutoConfiguration {
@Bean @Bean
@ConditionalOnBean(RpcEnhancementReporterProperties.class) @ConditionalOnBean(RpcEnhancementReporterProperties.class)
public ReactiveCircuitBreakerConfigModifier reactiveCircuitBreakerConfigModifier(RpcEnhancementReporterProperties properties) { @ConditionalOnMissingBean(CircuitBreakerConfigModifier.class)
return new ReactiveCircuitBreakerConfigModifier(properties); public CircuitBreakerConfigModifier reactiveCircuitBreakerConfigModifier(RpcEnhancementReporterProperties properties) {
} return new CircuitBreakerConfigModifier(properties);
public static class ReactiveCircuitBreakerConfigModifier implements PolarisConfigModifier {
private final RpcEnhancementReporterProperties properties;
public ReactiveCircuitBreakerConfigModifier(RpcEnhancementReporterProperties properties) {
this.properties = properties;
}
@Override
public void modify(ConfigurationImpl configuration) {
properties.setEnabled(true);
// Turn on circuitbreaker configuration
configuration.getConsumer().getCircuitBreaker().setEnable(true);
// Set excludeCircuitBreakInstances to true
RecoverRouterConfig recoverRouterConfig = configuration.getConsumer().getServiceRouter()
.getPluginConfig(ServiceRouterConfig.DEFAULT_ROUTER_RECOVER, RecoverRouterConfig.class);
recoverRouterConfig.setExcludeCircuitBreakInstances(true);
// Update modified config to source properties
configuration.getConsumer().getServiceRouter()
.setPluginConfig(ServiceRouterConfig.DEFAULT_ROUTER_RECOVER, recoverRouterConfig);
}
@Override
public int getOrder() {
return ContextConstant.ModifierOrder.CIRCUIT_BREAKER_ORDER;
}
} }
} }

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.rpc.enhancement.feign; package com.tencent.cloud.polaris.circuitbreaker.feign;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -28,7 +28,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation; import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation;
/** /**
* PolarisCircuitBreakerNameResolver * PolarisCircuitBreakerNameResolver.
* *
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */

@ -0,0 +1,69 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.circuitbreaker.gateway;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerFilterFactory;
import org.springframework.cloud.gateway.support.ServiceUnavailableException;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.DispatcherHandler;
import org.springframework.web.server.ResponseStatusException;
/**
* PolarisCircuitBreakerFilterFactory.
*
* @author seanyu 2023-02-27
*/
public class PolarisCircuitBreakerFilterFactory extends SpringCloudCircuitBreakerFilterFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(PolarisCircuitBreakerFilterFactory.class);
public PolarisCircuitBreakerFilterFactory(ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory,
ObjectProvider<DispatcherHandler> dispatcherHandlerProvider) {
super(reactiveCircuitBreakerFactory, dispatcherHandlerProvider);
}
@Override
public GatewayFilter apply(Config config) {
return super.apply(config);
}
@Override
protected Mono<Void> handleErrorWithoutFallback(Throwable t, boolean resumeWithoutError) {
if (t instanceof java.util.concurrent.TimeoutException) {
return Mono.error(new ResponseStatusException(HttpStatus.GATEWAY_TIMEOUT, t.getMessage(), t));
}
if (t instanceof CallAbortedException) {
LOGGER.debug("PolarisCircuitBreaker CallAbortedException: {}", t.getMessage());
return Mono.error(new ServiceUnavailableException());
}
if (resumeWithoutError) {
return Mono.empty();
}
return Mono.error(t);
}
}

@ -17,9 +17,7 @@
package com.tencent.cloud.polaris.circuitbreaker.reactor; package com.tencent.cloud.polaris.circuitbreaker.reactor;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.api.InvokeHandler; import com.tencent.polaris.circuitbreak.api.InvokeHandler;
import com.tencent.polaris.circuitbreak.api.pojo.InvokeContext;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -29,7 +27,7 @@ import reactor.core.publisher.FluxOperator;
import reactor.core.publisher.Operators; import reactor.core.publisher.Operators;
/** /**
* FluxOperator for PolarisCircuitBreaker * FluxOperator for PolarisCircuitBreaker.
* *
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */

@ -17,9 +17,7 @@
package com.tencent.cloud.polaris.circuitbreaker.reactor; package com.tencent.cloud.polaris.circuitbreaker.reactor;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.api.InvokeHandler; import com.tencent.polaris.circuitbreak.api.InvokeHandler;
import com.tencent.polaris.circuitbreak.api.pojo.InvokeContext;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -29,7 +27,7 @@ import reactor.core.publisher.MonoOperator;
import reactor.core.publisher.Operators; import reactor.core.publisher.Operators;
/** /**
* MonoOperator for PolarisCircuitBreaker * MonoOperator for PolarisCircuitBreaker.
* *
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */

@ -20,7 +20,6 @@ package com.tencent.cloud.polaris.circuitbreaker.reactor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.api.InvokeHandler; import com.tencent.polaris.circuitbreak.api.InvokeHandler;
import com.tencent.polaris.circuitbreak.api.pojo.InvokeContext; import com.tencent.polaris.circuitbreak.api.pojo.InvokeContext;
import org.reactivestreams.Subscription; import org.reactivestreams.Subscription;
@ -29,7 +28,7 @@ import reactor.core.publisher.BaseSubscriber;
import reactor.util.context.Context; import reactor.util.context.Context;
/** /**
* Reactor Subscriber for PolarisCircuitBreaker * Reactor Subscriber for PolarisCircuitBreaker.
* *
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */

@ -19,15 +19,13 @@ package com.tencent.cloud.polaris.circuitbreaker.reactor;
import java.util.function.Function; import java.util.function.Function;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.api.InvokeHandler; import com.tencent.polaris.circuitbreak.api.InvokeHandler;
import com.tencent.polaris.circuitbreak.api.pojo.InvokeContext;
import org.reactivestreams.Publisher; import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
/** /**
* Reactor Transformer for PolarisCircuitBreaker * Reactor Transformer for PolarisCircuitBreaker.
* *
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */

@ -15,14 +15,14 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.circuitbreaker; package com.tencent.cloud.polaris.circuitbreaker.util;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* PolarisCircuitBreakerUtils * PolarisCircuitBreakerUtils.
* *
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */

@ -1,5 +1,7 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerAutoConfiguration,\ com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerAutoConfiguration,\
com.tencent.cloud.polaris.circuitbreaker.config.ReactivePolarisCircuitBreakerAutoConfiguration com.tencent.cloud.polaris.circuitbreaker.config.ReactivePolarisCircuitBreakerAutoConfiguration,\
com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerFeignClientAutoConfiguration,\
com.tencent.cloud.polaris.circuitbreaker.config.GatewayPolarisCircuitBreakerAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\ org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerBootstrapConfiguration com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerBootstrapConfiguration

@ -25,7 +25,6 @@ import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.feign.DefaultEnhancedFeignPluginRunner; import com.tencent.cloud.rpc.enhancement.feign.DefaultEnhancedFeignPluginRunner;
import com.tencent.cloud.rpc.enhancement.feign.EnhancedFeignBeanPostProcessor; import com.tencent.cloud.rpc.enhancement.feign.EnhancedFeignBeanPostProcessor;
import com.tencent.cloud.rpc.enhancement.feign.EnhancedFeignPluginRunner; import com.tencent.cloud.rpc.enhancement.feign.EnhancedFeignPluginRunner;
import com.tencent.cloud.rpc.enhancement.feign.PolarisCircuitBreakerNameResolver;
import com.tencent.cloud.rpc.enhancement.feign.plugin.EnhancedFeignPlugin; import com.tencent.cloud.rpc.enhancement.feign.plugin.EnhancedFeignPlugin;
import com.tencent.cloud.rpc.enhancement.feign.plugin.reporter.ExceptionPolarisReporter; import com.tencent.cloud.rpc.enhancement.feign.plugin.reporter.ExceptionPolarisReporter;
import com.tencent.cloud.rpc.enhancement.feign.plugin.reporter.SuccessPolarisReporter; import com.tencent.cloud.rpc.enhancement.feign.plugin.reporter.SuccessPolarisReporter;
@ -74,11 +73,6 @@ public class RpcEnhancementAutoConfiguration {
@Role(RootBeanDefinition.ROLE_INFRASTRUCTURE) @Role(RootBeanDefinition.ROLE_INFRASTRUCTURE)
protected static class PolarisFeignClientAutoConfiguration { protected static class PolarisFeignClientAutoConfiguration {
@Bean
public PolarisCircuitBreakerNameResolver polarisCircuitBreakerNameResolver() {
return new PolarisCircuitBreakerNameResolver();
}
@Bean @Bean
public EnhancedFeignPluginRunner enhancedFeignPluginRunner( public EnhancedFeignPluginRunner enhancedFeignPluginRunner(
@Autowired(required = false) List<EnhancedFeignPlugin> enhancedFeignPlugins) { @Autowired(required = false) List<EnhancedFeignPlugin> enhancedFeignPlugins) {

Loading…
Cancel
Save