Hystrix 实现服务熔断与监控

5 minute

什么是服务熔断

概念

应对微服务雪崩效应的一种链路保护机制,类似保险丝。

雪崩效应

微服务之间的数据交互是通过远程调用来完成的。服务 A 调用服务,服务 B 调用服务 C,某一时间链路上对服务 C 的调用响应时间过长或者服务 C 不可用,随着时间的增长,对服务 C 的调用也越来越多,然后服务 C 崩溃了,但是链路调用还在,对服务 B 的调用也在持续增多,然后服务 B 崩溃,随之 A 也崩溃,导致雪崩效应

实现机制

当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用。

通过 Hystrix 实现服务熔断,Hystrix 会监控微服务间调用的状况,当失败的调用到一定阈值,就会启动熔断机制,断路器打开。而在一段时间之后,断路器会变为半开状态,此时允许部分微服务调用,如果都成功了,即不超过设定好的阈值,那么断路器将恢复为关闭状态。

如下图所示:(来自Martin Fowler大神的博客

hystrix

应用场景

微服务架构中,多个微服务相互调用出使用

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

测试

  1. 打开:http://{ip}:{port}/hystrix
  2. 监控:http://{ip}:{port}/actuator/hystrix.stream
  3. 访问 http://localhost:8001/payment/cir/1,可以正常访问;
  4. 多次访问http://localhost:8001/payment/cir/-1, 返回系统繁忙信息,发现断路器开启了:
  5. 此时,再访问http://localhost:8001/payment/cir/1,发现返回了系统繁忙信息;
  6. 多次访问http://localhost:8001/payment/cir/1,发现断路器关闭,恢复正常访问。

hystrix