SpringCloud 详解(十)

Hystrix(续二)

服务熔断

添加 Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@GetMapping("/payment/circuit/{id}")
@HystrixCommand(fallbackMethod = "paymentCircuitBreakerHandler", 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"), //错误阀值
})
public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
if (id < 0) {
throw new RuntimeException("id 不能为负数");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName() + "\t" + "调用成功,流水号:" + serialNumber;
}

public String paymentCircuitBreakerHandler(Integer id) {
return "id 不能为负数,请重试。当前 id:" + id;
}

测试

分别启动 Eureka-Server 和 Payment5 模块后,浏览器访问:127.0.0.1:8005/payment/circuit/997,能够正常调用。然后连续快速地多次访问:127.0.0.1:8005/payment/circuit/-997,调用的都是 fallback 方法,最后再多次访问:127.0.0.1:8005/payment/circuit/997,会发现一开始还是调用的 fallback 方法,但是多试几次之后就又恢复正常了。

断路器开启和关闭的条件:

  • 到达以下阀值,断路器将会开启:
  • 当满足一定的阀值的时候(默认10秒内超过20个请求次数)
  • 当失败率达到一定的时候(默认10秒内超过50%的请求失败)
  • 当开启的时候,所有请求都不会进行转发。
  • 一段时间之后(默认是5秒),这个时候断路器是半开状态,会让其中一个请求进行转发。如果成功,断路器会关闭,若失败,继续开启。

备注:

上面的注解参数,不懂的可以点击下面的链接进行查看。
https://segmentfault.com/a/1190000016024957

工作流程

  1. 创建 HystrixCommand (用在依赖的服务返回单个操作结果的时候)或 HystrixObserableCommand(用在依赖的服务返回多个操作结果的时候)对象。
  2. 执行命令。
  3. 响应是否已缓存?如果为此命令启用了请求缓存,并且请求的响应在缓存中可用,则此缓存的响应将立即返回。
  4. 检查断路器是否为打开状态?如果断路器是打开的,那么 Hystrix 不会执行命令,而是转接到 fallback 处理逻辑;如果断路器是关闭的,检查是否有可用资源来执行命令。
  5. 线程池/队列/信号量是否占满?如果已经被占满,那么 Hystrix 也不会执行命令,而是转接到 fallback 处理理辑。
  6. Hystrix 根据我们使用的对象来决定采取什么样的方式去请求依赖服务。
  7. Hystix 将处理后的信息报告给断路器,而断路器会维护一组计数器来统计这些数据。断路器会使用这些统计数据来决定是否要将断路器打开,来对某个依赖服务的请求进行熔断。
  8. 当命令执行失败的时候,Hystix 会进入 fallback 尝试回退处理,通常也称此操作为“服务降级”。
  9. 当 Hystrix 命令执行成功之后,它会将处理结果直接返回或是以 Observable 的形式返回。

图形化仪表盘

准备工作

创建一个 Module,一个空的 Maven 项目。并导入下面的依赖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

编写配置文件

1
2
3
4
5
6
7
server:
port: 9001

#仪表盘允许的监控服务域名
hystrix:
dashboard:
proxy-stream-allow-list: "localhost"

主启动类

1
2
3
4
5
6
7
8
9
10
11
12
13
package ml.guest997;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
@EnableHystrixDashboard //启动 Hystrix 仪表盘
public class Dashboard {
public static void main(String[] args) {
SpringApplication.run(Dashboard.class, args);
}
}

添加配置(Payment5 模块)

1
2
3
4
5
6
#配置服务监控路径
management:
endpoints:
web:
exposure:
include: "hystrix.stream"

测试

分别启动 Eureka-Server、Payment5 和 Dashboard 模块后,浏览器访问:127.0.0.1/hystrix,输入监控路径:http://localhost:8005/actuator/hystrix.stream,如下图。

浏览器开一个新窗口访问:127.0.0.1:8005/payment/circuit/997,会出现如下图的画面。