Spring Cloud Hystrix:熔断器
# 07.Spring Cloud Hystrix:熔断器
在微服务架构中,各个服务之间存在相互依赖。比如,服务A调用服务B和服务C,而服务B和服务C又调用其他服务。这样的依赖关系被称为“扇出”。当某个服务不可用或响应时间过长,可能会导致大量系统资源被占用,进而引发雪崩效应,导致系统崩溃。
# 1.Hystrix概念与功能
Hystrix是一个处理分布式系统延迟和容错的开源库,通过实现熔断器模式,保障系统的稳定性和弹性,它的原理就像是一种“熔断保险丝”开关装置。在发生错误时,它向调用方返回一个符合预期、可处理的响应,而不是让系统长时间等待或抛出无法处理的异常。这样可以确保后台服务的线程不会被长时间不必要地占用,避免单个故障导致整个分布式系统的服务中断,进而引发服务雪崩。Spring Cloud Hystrix对Hystrix进行了封装,提供了以下关键功能:
服务降级:在服务调用失败时,返回预设的降级响应,保证服务消费者的体验。
服务熔断:类似保险丝,当达到最大访问服务后,直接访问拒绝,拉闸限电,然后调用服务降级方法返回友好提示
线程隔离:通过独立线程池或信号量限制服务调用,防止单个服务故障耗尽系统资源。
请求缓存与合并:减少重复请求和资源消耗。
实时监控:提供Hystrix Dashboard监控服务健康状态。
在实际开发中,Hystrix都是和OpenFeign组件一起结合使用的,OpenFeign组件中已经包含了Hystrix,但是默认情况下,OpenFeign是没有开启Hystrix的功能,我们需要在application.yml配置文件中手动的开启Hystrix的功能。需要注意的是,OpenFeign虽然集成了Hystrix,但是如果你要使用Hystrix中的 @HystrixCommand等注解,那还是需要引入下面的依赖。
<!-- hystrix断路器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2
3
4
5
# 2.服务降级(Fallback)
服务出现故障时,给故障服务降级到事先准备好的故障处理结果,将此结果返回给服务消费者,如:客户端访问服务1,服务1调用服务2,服务2出现故障,Hystrix服务降级,返回一个可以处理的结果给服务1,服务1再以友好的错误界面返回给客户端。
当出现以下情况,服务器忙,不让客户端等待并立刻返回一个友好提示,fallback
- 程序运行异常
- 超时
- 服务熔断触发服务降级
- 线程池/信号量打满
在微服务架构中,服务降级应该加在调用其他服务的服务上面。具体来说,如果微服务A调用微服务B和C,而B和C又调用其他微服务,那么服务降级应该加在:
- 微服务A上,用于处理对微服务B和C的调用失败。
- 微服务B和C上,用于处理它们对其他微服务的调用失败。
# 3.服务熔断
通过熔断机制,可以防止故障扩散,提高系统整体稳定性。即使部分服务不可用,用户也可以通过服务降级fallback方法获得备用结果,提升用户体验。
熔断机制的三种状态:
熔断关闭状态(Closed)
- 服务正常时,熔断器处于关闭状态,不对调用做任何限制。
熔断开启状态(Open)
- 在固定时间内(默认10秒),如果接口调用错误率达到一个阈值(默认50%),熔断器进入开启状态。
- 在开启状态下,后续对该服务接口的调用直接执行本地的fallback方法,而不经过网络。
半熔断状态(Half-Open)
- 熔断开启状态持续一段时间后(默认5秒),熔断器进入半熔断状态。
- 半熔断状态下,熔断器允许有限流量调用该服务并监控成功率。
- 如果调用成功率达到预期,熔断器进入关闭状态;否则,重新进入开启状态。
# 4.熔断和降级区别
服务降级(Service Degradation):当A服务向B服务发送请求时,即使B服务不可用或响应时间过长,A服务依然会发送请求,但会返回一个预定义的降级结果。这种方式确保了A服务的稳定性和用户体验,但B服务仍然会受到请求压力。
熔断(Circuit Breaker):当B服务的故障率达到一定阈值时,A服务会主动停止向B服务发送请求,直接返回一个预定义的错误或降级结果。这种方式可以防止B服务的过载,进一步保护系统的稳定性。当B服务恢复正常后,A服务会恢复对B服务的请求。
# 5.代码使用
# 5.1开启feign的hystrix功能
我们这里还以之前的例子,我们为cloud-service2
加上服务降级,来防止调用service2服务出现故障,首先在application.yml中开启hystrix熔断:
feign:
hystrix:
enabled: true
2
3
# 5.2 定义Fallback类
定义Feign客户端接口和相应的Fallback类,然后关闭service1服务并重新启动service2服务调用localhost:9000/service2/hello
@FeignClient(name = "cloud-service1",fallback = CloudService1ClientFallback.class)
public interface CloudService1Client {
@GetMapping("/service1/hello")
String hello();
}
@Component
class CloudService1ClientFallback implements CloudService1Client {
@Override
public String hello() {
return "Service 1 is currently unavailable. Please try again later.";
}
}
2
3
4
5
6
7
8
9
10
11
12
13