SpringCloud Hystrix断路器-服务熔断与降级和HystrixDashboard
SpringCloud Hystrix服务降级实例总结
【1】服务熔断
熔断机制概述
熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务出错不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。
当检测到该节点微服务调用响应正常后,恢复调用链路。
在Spring Cloud框架里,熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是@HystrixCommand。
关于服务熔断可以参考大神论文:https://martinfowler.com/bliki/CircuitBreaker.html
【2】服务降级和服务熔断区别
在Hystrix中,服务降级(Service Degradation)和服务熔断(Circuit Breaker)是两种不同的容错机制,它们分别用于处理不同的场景和问题。下面是它们的主要区别:
① 服务熔断 (Circuit Breaker)
服务熔断的概念源于电力工程中的断路器,它用于防止电路过载。在软件系统中,当检测到某个依赖服务出现问题时,断路器会“打开”,阻止进一步的请求到达故障服务,从而避免了请求的堆积和资源的无效消耗。一旦断路器打开,Hystrix会直接调用降级逻辑,而不是尝试调用故障服务,直到断路器再次关闭。
- 触发原因:服务熔断通常是因为下游服务出现故障,比如响应时间过长、频繁失败或完全不可达。也就是当某服务调用失败达到
一定次数或比例
时,断路器会打开 - 目的:保护调用者不受故障服务影响,防止调用者因为等待无响应的服务而浪费资源(如线程)。
- 机制:当检测到故障模式时,熔断器将“打开”,直接拒绝后续的请求,而不是尝试调用可能失败的服务。这有助于避免故障传播,并且可以提供快速失败响应,让调用者可以立即知道调用失败。
- 状态转换:断路器有三个状态:关闭(Closed)、打开(Open)和半开(Half-Open)。当故障消除一段时间后,断路器会进入半开状态,允许小部分请求尝试调用,如果成功,则关闭断路器,否则再次打开。
② 服务降级 (Service Degradation)
服务降级是在系统整体负荷过高或服务出现异常时,提供一种退而求其次的处理方式。它通常发生在系统资源紧张或为了防止系统过载的情况下。降级逻辑通常会提供一个静态的、预计算的或简化的响应,以代替完整服务的调用。
- 触发原因:服务降级通常是在系统整体负荷较高或资源紧张时触发,旨在优先处理关键请求或减轻系统压力。
- 目的:通过提供一个简化的或降级的服务版本,确保核心功能仍然可用,同时避免系统过载。
- 机制:当系统检测到负载过高或其他降级条件时,会执行预先定义的降级逻辑,这通常涉及到提供一个静态的、预计算的或低质量的响应,而不是尝试调用完整的服务。
- 代码侵入性:服务降级往往需要在应用层面上明确实现,例如编写降级逻辑或fallback方法,以便在正常服务无法满足时调用。
③ 总结
-
服务熔断是一种自动化的故障隔离机制,用于快速响应故障服务调用,防止调用者线程池被耗尽。
-
服务降级是根据系统状态动态调整服务级别的一种策略,用于在资源受限时提供基础服务,避免系统过载。
-
服务降级每次都会先调用原服务方法,调用失败才会执行服务降级方法;服务熔断状态会直接调用服务降级方法。
在实践中,两者常常结合使用,以构建更具弹性和健壮性的分布式系统。Hystrix作为一个容错库,提供了这些机制的实现,允许开发者在微服务架构中更好地控制故障处理和资源管理。
【3】@HystrixCommand熔断实例
服务提供方的方法上使用@HystrixCommand进行配置,如下所示(在10s内的10次请求中如果失败超过6次进入服务熔断):
// 服务熔断
@HystrixCommand(fallbackMethod = "paymentInfo_Circuit",commandProperties = {@HystrixProperty(name="circuitBreaker.enabled",value = "true"),//是否开启断路器@HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "10"),// 请求次数@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "10000"),// 时间窗口期@HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "60")// 失败率// 加起来就是在10s内的10次请求中如果失败超过6次进入服务熔断
})
public String paymentCircuitBreaker(@PathVariable("id") Integer id){if (id<0){throw new RuntimeException("id 不能为负数");}String serialNumber = IdUtil.simpleUUID();return "调用成功:"+serialNumber;
}public String paymentInfo_Circuit(Integer id){return "id不能为负数:"+id;
}
主启动类配置注解@EnableCircuitBreaker
。