Hystrix 实现服务熔断与监控
什么是服务熔断
概念
应对微服务雪崩效应的一种链路保护机制,类似保险丝。
雪崩效应
微服务之间的数据交互是通过远程调用来完成的。服务 A 调用服务,服务 B 调用服务 C,某一时间链路上对服务 C 的调用响应时间过长或者服务 C 不可用,随着时间的增长,对服务 C 的调用也越来越多,然后服务 C 崩溃了,但是链路调用还在,对服务 B 的调用也在持续增多,然后服务 B 崩溃,随之 A 也崩溃,导致雪崩效应。
实现机制
当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用。
通过 Hystrix 实现服务熔断,Hystrix 会监控微服务间调用的状况,当失败的调用到一定阈值,就会启动熔断机制,断路器打开。而在一段时间之后,断路器会变为半开状态,此时允许部分微服务调用,如果都成功了,即不超过设定好的阈值,那么断路器将恢复为关闭状态。
如下图所示:(来自Martin Fowler大神的博客)
应用场景
微服务架构中,多个微服务相互调用出使用
Hystrix 实现服务熔断
依赖导入
1<dependency>
2 <groupId>org.springframework.cloud</groupId>
3 <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
4</dependency>
5<dependency>
6 <groupId>org.springframework.cloud</groupId>
7 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
8</dependency>
实现服务熔断
启动类添加 @EnableHystrix 注解,表示使用熔断器,接着编写服务:
1// PaymentService.java
2public interface PaymentService {
3 ...
4 String circuitBreaker(Integer id);
5}
在实现类设置服务熔断的核心配置:
1// (1)启用断路器:
2@HystrixProperty(name = "circuitBreaker.enabled", value = "true")
3
4// (2)设置请求次数:
5@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10")
6
7// (3)设置时间窗口期:
8@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000")
9
10// (4)设置失败率:
11@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")
如上设置的值,如果在 10 秒内,失败率达到请求次数(10)的百分之 60,也就是 6 次,就会打开断路器,否则断路器依然关闭。
断路器打开后,在一定时间之后,断路器变为半开状态,允许部分请求访问,如果这些请求满足要求,不超阈值,则断路器恢复为关闭状态。
1@Service
2public class PaymentServiceImpl implements PaymentService {
3 ...
4 @Override
5 @HystrixCommand(fallbackMethod = "circuitBreaker_fallback",
6 commandProperties = {
7 @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
8 @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
9 @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
10 @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")
11 })
12 public String circuitBreaker(Integer id) {
13 if (id < 0) throw new RuntimeException("id 不能小于0");
14 String uuid = IdUtil.simpleUUID();
15 return Thread.currentThread().getName() + "\t" + "uuid:" + uuid;
16 }
17 public String circuitBreaker_fallback(@PathVariable("id") Integer id) {
18 return "id 不能小于0, 请重试~ id: " + id;
19 }
20}
接着编写接口:
1// PaymentController.java
2@RestController
3@Slf4j
4public class PaymentController {
5 @Resource
6 private PaymentService paymentService;
7
8 @GetMapping("/payment/cir/{id}")
9 public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
10 return paymentService.circuitBreaker(id);
11 }
12 ...
Hystrix 实现服务监控
依赖导入
1<dependency>
2 <groupId>org.springframework.cloud</groupId>
3 <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
4</dependency>
基本配置
启动类开启 @EnableHystrixDashboard
注解。
在要监控的服务的配置文件中添加:
1# hystrix 9001监控配置
2management:
3endpoints:
4 web:
5 exposure:
6 include: hystrix.stream, info, health
测试
- 打开:
http://{ip}:{port}/hystrix
; - 监控:
http://{ip}:{port}/actuator/hystrix.stream
; - 访问
http://localhost:8001/payment/cir/1
,可以正常访问; - 多次访问
http://localhost:8001/payment/cir/-1
, 返回系统繁忙信息,发现断路器开启了: - 此时,再访问
http://localhost:8001/payment/cir/1
,发现返回了系统繁忙信息; - 多次访问
http://localhost:8001/payment/cir/1
,发现断路器关闭,恢复正常访问。