有奖:语音产品征文挑战赛等你来> HOT

熔断场景

Spring Cloud Tencent CircuitBreaker 结合 Polaris 的熔断能力提供了标准的熔断实现,并提供服务级、接口级、节点级三种熔断级别,可以根据需求组合搭配,来实现期望的熔断效果。
本文介绍在本地开发 Java 应用,通过 Spring Cloud 的方式接入 TSE 治理中心(北极星网格),使用服务熔断功能。

前提条件

1. 在开始开发前,请确保您已经参见 下载 Maven下载安装了 Java 和 Maven。
2. 已创建 TSE 治理中心(北极星网格)实例,操作步骤详情参见 引擎管理

操作步骤

步骤1:引入依赖

1.1 引入 spring cloud tencent 依赖

修改应用根目录下的 pom.xml,添加dependencyManagement
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId>
<version>${version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
注意:
请根据项目 Spring Boot 和 Spring Framework 的版本,选择合适的 Spring Cloud Tencent 版本
服务级熔断支持版本号大于1.10.0的 Spring Cloud Tencent 版本

1.2 引入 spring cloud tencent starter

说明:
因为熔断能力依赖服务发现能力,所以需要主调方和被调方都引入服务注册与发现依赖。
方式一:只引入spring-cloud-starter-tencent-polaris-circuitbreaker
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
</dependency>
方式二:通过spring-cloud-starter-tencent-all引入 sct 所有 starters。
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-all</artifactId>
<!-- 注意需要指定 type=pom-->
<type>pom</type>
</dependency>
如果使用 Spring Cloud 2020 及以后版本,还需要添加如下依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

步骤2:增加相关配置文件并设置熔断方法

Spring Cloud Tencent 支持 Feign、RestTemplate、WebClient、Spring Cloud Gateway 四种组件的熔断,并会自动拉取您在北极星上为被调服务配置的熔断规则进行熔断。选择您适合的方式配置即可。
Feign
RestTemplate
WebClient
Spring Cloud Gateway
完整代码可查看 Demo
1. 添加 Feign 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2. 添加 Feign 配置文件
spring:
application:
name: polaris-circuitbreaker-feign-example
cloud:
openfeign:
circuitbreaker:
enabled: true
polaris:
address: grpc://${修改为 Polaris 服务地址}:8091
namespace: default
enabled: true
loadbalancer:
enabled: true
circuitbreaker:
enabled: true
3. 设置 Feign 熔断方法
声明 Feign 调用
当 Feign fallback 不配置时,会在熔断发生时,从 polaris server 拉取降级配置,进行降级,降级的 response body 会序列化成您在 Feign 中配置的返回对象,请确保能正确的序列化。
@Primary
@FeignClient(name = "polaris-circuitbreaker-callee-service", fallback = ProviderBFallback.class)
public interface ProviderB {

/**
* Get info of service B.
*
* @return info of service B
*/
@GetMapping("/example/service/b/info")
String info();
}
声明本地 Feign 熔断方法(可选)
@Component
public class ProviderBFallback implements ProviderB {

@Override
public String info() {
return "fallback: trigger the refuse for service b";
}
}
发起 Feign 调用
@RestController
@RequestMapping("/example/service/a")
public class ServiceAController {

@Autowired
private ProviderB polarisServiceB;

/**
* Get info of Service B by Feign.
* @return info of Service B
*/
@GetMapping("/getBServiceInfo")
public String getBServiceInfo() {
return polarisServiceB.info();
}


完整代码可查看 Demo
1. 添加 RestTemplate 配置文件
spring:
application:
name: polaris-circuitbreaker-resttemplate-example
cloud:
polaris:
address: grpc://${修改为 Polaris 服务地址}:8091
namespace: default
enabled: true
loadbalancer:
enabled: true
circuitbreaker:
enabled: true
2. 设置 RestTemplate 熔断方法
设置 RestTemplate bean,添加@PolarisCircuitBreaker注解。
@Bean
@LoadBalanced
@PolarisCircuitBreaker
public RestTemplate restTemplate() {
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://polaris-circuitbreaker-callee-service");
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(uriBuilderFactory);
return restTemplate;
}
说明:
@PolarisCircuitBreaker 包含两个参数:
String 类型的 fallback 表示返回希望降级的 response body string
PolarisCircuitBreakerFallback 类型的 fallbackClass 表示返回希望降级的具体 response,需要自定义实现 PolarisCircuitBreakerFallback#fallback()方法,返回 PolarisCircuitBreakerHttpResponse
两个参数不能同时配置。 当 @PolarisCircuitBreaker不配置任何参数时,会在熔断发生时,从 polaris server 拉取降级配置,进行降级,降级的 response body 会序列化成您在 RestTemplate 中配置的返回对象,请确保能正确的序列化。
3. 发起 RestTemplate 调用
@RestController
@RequestMapping("/example/service/a")
public class ServiceAController {

@Autowired
private RestTemplate restTemplate;

@GetMapping("/getBServiceInfo")
public String getBServiceInfo() {
return restTemplateFallbackFromPolaris.getForEntity("/example/service/b/info", String.class);
}
}
完整代码可查看demo
1. 添加 WebFlux 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
2. 设置 WebClient 配置文件
spring:
application:
name: polaris-circuitbreaker-webclient-example
cloud:
polaris:
address: grpc://${修改为 Polaris 服务地址}:8091
namespace: default
enabled: true
loadbalancer:
enabled: true
circuitbreaker:
enabled: true
3. 设置 WebClient 熔断方法
设置 WebClient bean
@LoadBalanced
@Bean
WebClient.Builder webClientBuilder() {
return WebClient.builder()
.baseUrl("http://polaris-circuitbreaker-callee-service");
}
发起 WebClient 调用
@RestController
@RequestMapping("/example/service/a")
public class ServiceAController {

@Autowired
private ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory;

@Autowired
private WebClient.Builder webClientBuilder;

@GetMapping("/getBServiceInfo")
public Mono<String> getBServiceInfo() {
return webClientBuilder
.build()
.get()
.uri("/example/service/b/info")
.retrieve()
.bodyToMono(String.class)
.transform(it ->
reactiveCircuitBreakerFactory
// create 的参数为被调服务的服务名
.create("polaris-circuitbreaker-callee-service")
// 熔断降级方法
.run(it, throwable -> Mono.just("fallback: trigger the refuse for service b"))
);
}

}
完整代码可查看demo
1. 添加 Spring Cloud Gateway 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
2. 设置 Spring Cloud Gateway 配置文件
以 gateway.discovery.locator 形式配置
spring:
application:
name: GatewayScgService
cloud:
polaris:
address: grpc://${修改为 Polaris 服务地址}:8091
namespace: default
enabled: true
gateway:
discovery:
locator:
enabled: true
'predicates[0]':
name: Path
args:
patterns: '''/'' + serviceId + ''/**'''
'filters[0]':
name: RewritePath
args:
regexp: '''/'' + serviceId + ''/(?<remaining>.*)'''
replacement: '''/$\\{remaining}'''
'filters[1]':
# 配置熔断 Filter
name: CircuitBreaker
args:
# statusCodes,可选参数,配置熔断的匹配返回码,缺省时会自动识别 "5**" 为错误,可以为"4**,5**"的形式,也可以为具体的返回码
statusCodes: '''404,5**'''
# fallbackUri,可选参数,配置熔断降级的转发路由方法,缺省时会在熔断触发后拉取 plaris server 配置的降级作为 response
fallbackUri: '''forward:/polaris-fallback'''
以普通路由形式配置形式配置
spring:
application:
name: GatewayScgService
cloud:
polaris:
address: grpc://${修改为 Polaris 服务地址}:8091
namespace: default
enabled: true
gateway:
routes:
- id: polaris-circuitbreaker-callee-service
uri: lb://polaris-circuitbreaker-callee-service
predicates:
- Path=/polaris-circuitbreaker-callee-service/**
3. 设置 Spring Cloud Gateway 熔断方法
设置熔断降级的转发路由方法
@RestController
public class FallbackController {

@GetMapping("/polaris-fallback")
Mono<String> getFallback() {
return Mono.just("fallback: trigger the refuse for service b");
}
}

步骤3:验证

启动应用并在 北极星控制台 设置被调服务的服务级熔断规则;请参见 服务治理指南 > 服务治理 > 熔断降级 > 服务熔断与主动探测 相关文档,相关界面如下:

为了验证熔断能力,被调端至少启动两个实例,一个返回成功,一个返回失败。
测试主调方向被调方发起服务调用,前几个请求会出现往有问题的服务发起调用,当问题数达到您在北极星控制台配置的熔断阈值时,即会触发熔断,主调方不再发起调用,直接返回熔断降级方法。