SpringCloud Circuit breaker(断路器)提供了跨不同断路器实现的抽象。它提供了在应用程序中使用的一致API,允许开发人员选择最适合应用程序需要的断路器实现。
环境:Springboot2.3.12.RELEASE +
cloud-netflix-hystrix2.2.10.RELEASE
简介
SpringCloud Circuit breaker(断路器)提供了跨不同断路器实现的抽象。它提供了在应用程序中使用的一致API,允许开发人员选择最适合应用程序需要的断路器实现。
支持的断路器类型:
- Netfix Hystrix
- Resilience4J
- Sentinel
- Spring Retry
核心概念
要在代码中创建断路器(circuit breaker),可以使用断路器工厂API。当您在类路径中包含Spring Cloud Circuit Breaker starter时,将自动创建一个实现此API的bean。下面给出了使用此API的一个非常简单的示例:@Service
public static class DemoService {
private RestTemplate rest;
private CircuitBreakerFactory cbFactory;
public DemoService(RestTemplate rest, CircuitBreakerFactory cbFactory) {
this.rest = rest;
this.cbFactory = cbFactory;
}
public String slow() {
// 通过默认的CircuitBreakerFactory工厂创建一个指定id(名称)的断路器
// run方法是实际执行你的业务方法,第二个参数throwable 是当发生异常或者是执行超时
// 执行的回退(降级)处理
return cbFactory.create("slow").run(() -> rest.getForObject("/slow", String.class), throwable -> "fallback");
}
} 项目配置
通过引入下面不同依赖来确定使用具体的那个断路器
- Hystrix - org.springframework.cloud:spring-cloud-starter-netflix-hystrix
- Resilience4J - org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j
- Reactive Resilience4J - org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j
- Spring Retry - org.springframework.cloud:spring-cloud-starter-circuitbreaker-spring-retry
- Sentinal - org.springframework.cloud:spring-cloud-starter-circuitbreaker-sentinal
以上5种断路器是不同的实现方式,根据需要引入即可。
示例
这里以Hystrix为例来使用
引入依赖
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
2.2.10.RELEASE 定义具有熔断功能的服务@Service
public class DemoService {
private RestTemplate rest;
// 注入系统默认的实现
private CircuitBreakerFactory cbFactory;
public DemoService(RestTemplate rest, CircuitBreakerFactory cbFactory) {
this.rest = rest;
this.cbFactory = cbFactory;
}
public String slow() {
// 使用系统默认的实现创建断路器进行业务的处理
return cbFactory.create("slow").run(() -> rest.getForObject("http://localhost:8080/demos/slow", String.class), throwable -> "fallback");
}
public String slow2() {
// 使用自定义的断路器工厂进行业务的处理
return cbf().create("demo-slow").run(() -> rest.getForObject("http://localhost:8080/demos/slow", String.class), throwable -> "fallback");
}
// 可以将这个定义为Bean来覆盖系统默认的实现,在系统默认的实现上有条件限定
private CircuitBreakerFactory cbf() {
HystrixCircuitBreakerFactory cbf = new HystrixCircuitBreakerFactory() ;
// 配置线程池
HystrixThreadPoolProperties.Setter threadPoolProperties = HystrixThreadPoolProperties.Setter() ;
threadPoolProperties.withCoreSize(5)
.withKeepAliveTimeMinutes(5)
.withMaxQueueSize(Integer.MAX_VALUE)
.withQueueSizeRejectionThreshold(1000) ;
// 配置默认的执行行为属性
HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter() ;
commandProperties.withCircuitBreakerEnabled(true)
// 当请求超过了3s那么断路器就会工作进行回退(降级处理),执行上面run方法中的第二个参数
.withExecutionTimeoutInMilliseconds(3000)
.withRequestCacheEnabled(true)
// 隔离策略有两种THREAD,SEMAPHORE
// THREAD: 避免线程被阻塞
// SEMAPHORE: 适合高并发限流处理;因为线程池的方式一般不会创建过多的线程
// 线程是有限的,在高并发情况下是没法满足响应处理的。
.withExecutionIsolationStrategy(ExecutionIsolationStrategy.THREAD);
// 将其加入到集合中,为不同的服务创建不同的配置
cbf.configure(builder -> {
builder.commandProperties(commandProperties).groupName("demo") ;
}, "demo-slow");
// 当默认的id不存在时使用这默认的配置
cbf.configureDefault(id -> {
HystrixCommand.Setter setter = HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey("demo")) // 服务分组,大的模块
.andCommandKey(HystrixCommandKey.Factory.asKey("demo-slow")) // 服务标识(具体服务分组中的某一个子的服务),子模块
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("demo-pools")) // 线程池名称
.andThreadPoolPropertiesDefaults(threadPoolProperties) // 线程池相关配置
.andCommandPropertiesDefaults(commandProperties) ; // 执行时相关属性配置
return setter ;
});
return cbf ;
}
} Controller接口@RestController
@RequestMapping("/demos")
public class DemoController {
@Resource
private DemoService demoService ;
@GetMapping("/index")
public Object index() {
return demoService.slow2() ;
}
@GetMapping("/slow")
public Object slow() {
try {
TimeUnit.SECONDS.sleep(5) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
return "slow" ;
}
} 原理
CircuitBreakerFactory#create方法创建了CircuitBreaker实例
根据当前的CLASSPATH我们使用的是Hystrix,那么这里使用的工厂就是:
HystrixCircuitBreakerFactory类public class HystrixCircuitBreakerFactory extends CircuitBreakerFactory { 泛型参数:Setter就是用来配置Hystrix相关配置信息的(这里主要用来CommandKey与Setter进行绑定),HystrixConfigBuilder用来构建 HystrixCommand.Setter对象。
当执行HystrixCircuitBreakerFactory#configure方法时:public abstract class AbstractCircuitBreakerFactory 断路器具体的子类实现HystrixCircuitBreakerFactory// 子类继承的父类中的泛型:第一个泛型参数:需要构建什么样的一个配置,第二个泛型参数:通过谁来构建第一个泛型参数配置
public class HystrixCircuitBreakerFactory extends CircuitBreakerFactory {
public HystrixConfigBuilder configBuilder(String id) {
return new HystrixConfigBuilder(id);
}
public static class HystrixConfigBuilder extends AbstractHystrixConfigBuilder {
public HystrixConfigBuilder(String id) {
super(id);
}
// 从这里也看出来最终Builder就是用来构建Setter对象用
@Override
public HystrixCommand.Setter build() {
return HystrixCommand.Setter.withGroupKey(getGroupKey())
.andCommandKey(getCommandKey())
.andCommandPropertiesDefaults(getCommandPropertiesSetter());
}
}
} 断路器工厂有了,接下来就是通过工厂创建具体的断路器对象了
通过上面的代码执行cbf().create("demo-slow")方法时执行了什么?public class HystrixCircuitBreakerFactory extends CircuitBreakerFactory {
private Function defaultConfiguration = id -> HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(getClass().getSimpleName()))
.andCommandKey(HystrixCommandKey.Factory.asKey(id));
public HystrixCircuitBreaker create(String id) {
// 通过上面分析最终所有的Hystrix的Setter会与id绑定存入一个Map中
// 这里computeIfAbsent方法先从集合中通过id获取,如果获取不到则将第二个参数存入集合中返回
HystrixCommand.Setter setter = getConfigurations().computeIfAbsent(id, defaultConfiguration);
return new HystrixCircuitBreaker(setter);
}
} 上面创建的是HystrixCircuitBreaker断路器,当执行run方法时:public class HystrixCircuitBreaker implements CircuitBreaker {
private HystrixCommand.Setter setter;
public HystrixCircuitBreaker(HystrixCommand.Setter setter) {
this.setter = setter;
}
@Override
public T run(Supplier toRun, Function fallback) {
// 最终执行的就是Hystrix的核心 HystrixCommand对象
HystrixCommand command = new HystrixCommand(setter) {
@Override
protected T run() throws Exception {
return toRun.get();
}
@Override
protected T getFallback() {
return fallback.apply(getExecutionException());
}
};
return command.execute();
}
} 原文链接:https://www.toutiao.com/a7036197230167982630/
|