一、Hystrix 断路器
1. 分布式微服务面临的问题
微服务之间调用难免会出现问题,比如 A 服务调用 B 服务和 C 服务,B 服务和 C 服务又调用其他服务,如果在这个过程中有某个服务不响应或长时间不可用,对 A 服务的调用就会占用越来越多的系统资源,进而引起系统的崩溃,这就是所谓的 雪崩效应 。
2. Hystrix 介绍
Hystrix 是一个用于处理分布式系统的 延迟 和 容错 的开源库,能够保证在一个依赖出现问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
处理方式就是向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间等待或者抛出调用方无法处理的异常。
3. 主要功能
服务降级 Fallback
比如 A 服务调用 B 服务,A 等待 B 的响应时间是 3 秒,而 B 服务当前繁忙,处理请求消耗了 5 秒,这就会造成 TimeOut 的异常导致前端报错。
而服务降级就是如果 B 没有正常响应,那么将提前设置好的返回值返回给 A 。
可能触发降级的情况:
- 程序运行异常
- 超时自动降级
- 服务熔断触发服务降级
- 信号池/信号量打满也会导致服务降级
- 人工降级
服务熔断 Breaker
比如 A 服务访问 B 服务,每次 B 服务都进行降级处理,到达一定次数后就对 B 进行熔断操作,比如设置的熔断时长是10秒钟,在这期间 B 直接进行降级处理返回备选数据,不再等待 B 响应。10秒过后尝试访问 B 服务,如果 B 依旧进行降级操作,则继续熔断,如果 B 正常响应,则结束熔断。
概括起来就好比保险丝,访问量达到最大以后直接拒接访问。
注:访问量高时优先进行降级处理,降级到一定次数后进行熔断处理
服务限流 Flowlimit
秒杀高并发等操作,防止一窝蜂进来,将访问排序,一次N个,有序进行。
接近实时的监控
有前端展示的界面,对整个链路实时监控。
4. Hystrix已经停止更新
虽然已经停止更新,并且已经有了替代产品,但还是需要了解和掌握。
二、当前项目结构介绍
当前项目中包含五个模块:
- 公有API:cloud-api-commons
- 服务提供者: cloud-provider-payment8001/8002 (端口号8001 和 8002 )
- 服务消费者(restTemplate): cloud-consumer-order80 (端口号80 )
- 服务消费者(OpenFeign): cloud-consumer-feign-order80(端口号80 )
- 注册中心 Eureka: cloud-eureka-server7001(端口号7001 )
前文链接: https://blog.youkuaiyun.com/weixin_42547014/article/details/120334570
项目源码:https://gitee.com/zhangchouchou/spring-cloud-demo
三、项目中添加 Hystrix 并进行简单的压力测试
1. 新建模块
命名为 cloud-provider-hystrix-payment8001,依旧以 Maven 形式创建
2. 修改 POM 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>SpringCloudDemo</artifactId>
<groupId>org.zjh.springclouddemo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-provider-hystrix-payment8001</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!--新增hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--Eureka-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.zjh.springclouddemo</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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>
</project>
3. 新增 YML
server:
port: 8001
spring:
application:
name: cloud-hystrix-payment-service
eureka:
client:
# 是否往eureka注册
register-with-eureka: true
# 是否获取注册信息
fetch-registry: true
# server端地址
service-url:
defaultZone: http://localhost:7001/eureka/
4. 新增启动类
包名依旧和其它模块包名相同
@SpringBootApplication
// Eureka客户端
@EnableEurekaClient
public class PaymentHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(PaymentHystrixApplication.class,args);
}
}
5.创建业务类
//PaymentService.java
public interface PaymentService {
public String paymentInfo_OK(Integer id);
public String payment_Timeout(Integer id);
}
//PaymentServiceImpl.java
@Service
public class PaymentServiceImpl implements PaymentService {
//成功
public String paymentInfo_OK(Integer id){
return "线程池:"+Thread.currentThread().getName()+" paymentInfo_OK,id: "+id;
}
//失败
public String payment_Timeout(Integer id){
int timeNumber = 3;
try { TimeUnit.SECONDS.sleep(timeNumber); }catch (Exception e) {e.printStackTrace();}
return "线程池:"+Thread.currentThread().getName()+" paymentInfo_TimeOut,id: "+id+"\t"+" 耗时(秒)"+timeNumber;
}
}
6. 创建 Controller
@RestController
@Slf4j
public class PaymentController {
@Autowired
private PaymentService paymentService;
@Value("${server.port}")
private String serverPort;
@GetMapping("/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id){
String result = paymentService.paymentInfo_OK(id);
log.info("*******result:"+result);
return result;
}
@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
String result = paymentService.payment_Timeout(id);
log.info("*******result:"+result);
return result;
}
}
项目结构如下所示
7. 测试
首先访问注册中心,发现服务已经注册上
然后依次访问
http://localhost:8001/payment/hystrix/ok/31
http://localhost:8001/payment/hystrix/timeout/31
8.简单的高并发测试
我们使用 Jmeter 进行高并发压力测试
压测访问需要等待3秒的那个路径(http://localhost:8001/payment/hystrix/timeout/31
),可以看到控制台瞬间打印出许多条数据
2021-09-18 15:31:41.241 INFO 4152 --- [io-8001-exec-47] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-47 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.241 INFO 4152 --- [io-8001-exec-52] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-52 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.241 INFO 4152 --- [o-8001-exec-191] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-191 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.257 INFO 4152 --- [io-8001-exec-34] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-34 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.257 INFO 4152 --- [o-8001-exec-155] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-155 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.257 INFO 4152 --- [io-8001-exec-83] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-83 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.257 INFO 4152 --- [io-8001-exec-73] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-73 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.273 INFO 4152 --- [io-8001-exec-24] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-24 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.273 INFO 4152 --- [io-8001-exec-65] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-65 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.273 INFO 4152 --- [io-8001-exec-70] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-70 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.288 INFO 4152 --- [io-8001-exec-56] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-56 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.288 INFO 4152 --- [io-8001-exec-12] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-12 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.288 INFO 4152 --- [o-8001-exec-171] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-171 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.319 INFO 4152 --- [io-8001-exec-37] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-37 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.319 INFO 4152 --- [o-8001-exec-133] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-133 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.319 INFO 4152 --- [io-8001-exec-17] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-17 paymentInfo_TimeOut,id: 31 耗时(秒)3
2021-09-18 15:31:41.319 INFO 4152 --- [io-8001-exec-75] o.z.s.controller.PaymentController : *******result:线程池:http-nio-8001-exec-75 paymentInfo_TimeOut,id: 31 耗时(秒)3
然后访问另一个响应路径(http://localhost:8001/payment/hystrix/ok/31),发现需要短暂等待后才能得到响应结果。这说明响应速度和服务复杂度没有直接关系。
而出现等待的原因因该是tomcat的默认的工作线程数被打满了,没有多余的线程来分解压力和处理。
四、使用 Hystrix 进行模块间调用
1. 新增模块
命名为 cloud-consumer-feign-hystrix-order80
2. 修改 POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>SpringCloudDemo</artifactId>
<groupId>org.zjh.springclouddemo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-consumer-feign-hystrix-order80</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!--新增hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--Eureka-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.zjh.springclouddemo</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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>
</project>
3. 创建 YML
server:
port: 80
spring:
application:
name: cloud-provider-hystrix-payment-service
eureka:
client:
# 是否注册到eureka
register-with-eureka: true
# 是否发现相关服务
fetch-registry: true
# 指定路径
service-url:
defaultZone: http://localhost:7001/eureka
4. 创建启动类
@SpringBootApplication
// Eureka客户端
@EnableEurekaClient
//服务调用方开启Feign
@EnableFeignClients
public class OrderHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(OrderHystrixApplication.class,args);
}
}
5. 创建业务类
@FeignClient("CLOUD-HYSTRIX-PAYMENT-SERVICE")
public interface PaymentHystrixService {
@GetMapping("/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id);
@GetMapping("/payment/hystrix/timeout/{id}")
public String payment_Timeout(@PathVariable("id") Integer id);
}
6. 创建 Controller
@RestController
@Slf4j
public class OrderHystrixController {
@Resource
private PaymentHystrixService paymentHystrixService;
@GetMapping("/consumer/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id){
String result = paymentHystrixService.paymentInfo_OK(id);
log.info("*******result:"+result);
return result;
}
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
String result = paymentHystrixService.payment_Timeout(id);
log.info("*******result:"+result);
return result;
}
}
7. 测试
访问80端口,测试模块间调用是否成功
8. 高并发测试
启动压测工具,使用两千并发量压测8001端口,然后使用 80 端口调用 8001 端口。通过上一个测试可以证明 80 端口可以成功调用 8001 端口。下面是测试结果。
因为 tomcat 线程里面的工作线程已经被挤占完毕,导致 8001 同一层次的其他接口服务被困死,80 端口再去调用 8001 端口导致请求超时,这说明高并发的情况下再简单的程序也会出现异常。
五、实现服务降级
1. 给服务提供者 8001 端口添加 fallback
1). 修改主启动类
在启动类上添加 @EnableCircuitBreaker
启用 Hystrix
2). 业务类启用降阶处理
为了方便演示,在休眠3秒的 payment_Timeout
方法上添加超时降级的处理方法,处理方式是使用 @HystrixCommand
注解,并将 payment_Timeout
方法内的等待时长改为 15 秒。
/**
* fallbackMethod 表示服务降级后执行的方法名
* commandProperties属性是一个@HystrixProperty数组,@HystrixProperty必须指定name和value属性
* 下面注解中的 name 表示超时降级 ,时长 5 秒,也就是如果5秒内没有响应就执行超时降级方法。
**/
@HystrixCommand(
fallbackMethod = "payment_TimeoutHandler",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000") //5秒钟以内就是正常的业务逻辑
})
服务超时方法
public String payment_TimeoutHandler(Integer id) {
return "线程池:"+Thread.currentThread().getName()+" payment_TimeoutHandler,系统繁忙,请稍后再试\t ";
}
注:若方法中出现错误,比如 int i = 1/0
,同样也会走超时方法,不过不需要等 5 秒钟
3). 测试
访问 http://localhost:8001/payment/hystrix/timeout/1
后等待5秒后成功返回超时降级结果
2. 消费者降级
注意:服务降级可以在服务提供者侧,也可以在服务消费者侧。更多是在服务消费者侧。
1). 在 YML 中添加配置
feign:
hystrix:
enabled: true #如果处理自身的容错就开启。开启方式与生产端不一样。
2). 主启动类添加注解 @EnableHystrix
3). 添加降级注解和兜底方法
//超时降级演示
@HystrixCommand(fallbackMethod = "payment_TimeoutHandler",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")//超过1.5秒就降级自己
})
//兜底方法,上面方法出问题,我来处理,返回一个出错信息
public String payment_TimeoutHandler(Integer id) {
return "我是消费者80,对方支付系统繁忙请10秒后再试。或自己运行出错,请检查自己。";
}
4). 测试
访问 http://localhost/consumer/payment/hystrix/timeout/32
,配置成功
3. 创建全局兜底方法
在目前的代码中,不难发现有一个很大的问题——每个业务方法对应一个兜底的方法,导致代码臃肿,耦合性高,不方便维护等等。
但在实际应用中,除了几个重要的业务有单独的降级方法外,其余的大多数都是用一个全局的方法。
创建全局方法步骤如下:
1). 添加 @DefaultProperties 注解
在 Controller 上添加 @DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
注解, payment_Global_FallbackMethod
为全局方法名
将 @HystrixCommand(fallbackMethod = "",commandProperties = {})
改为 @HystrixCommand
2). 测试
再次访问 http://localhost/consumer/payment/hystrix/timeout/32
,测试成功。
4. 创建服务降级类
在上述方法中使用全局兜底方法后可以解决代码耦合问题,但服务降级方法和业务逻辑混在一起导致项目结构混乱。
所以,我们需要添加一个服务降级处理的实现类来继续实现解耦。
服务降级处理是在客户端80实现完成的,与服务端8001没有关系,解决思路是为Feign客户端定义的接口添加服务降级处理的实现类。
1). 创建实现类
创建 PaymentFallbackService
类实现 PaymentHystrixService
接口
PaymentHystrixService
接口为 80 与 8001 模块之间的远程调用接口。
@Component
public class PaymentFallbackService implements PaymentHystrixService{
@Override
public String paymentInfo_OK(Integer id) {
return "-----PaymentFallbackService fallback : paymentInfo_OK";
}
@Override
public String payment_Timeout(Integer id) {
return "-----PaymentFallbackService fallback : paymentInfo_TimeOut";
}
}
2). 修改被继承接口上的注解
修改 PaymentHystrixService
接口的 @FeignClient
注解,并添加 @Component
注解
3). YML 中添加配置
在之前的步骤中已经添加该配置
feign:
hystrix:
enabled: true
4). 将 Controller 中的全局配置去掉
5). 测试
修改完成后重启服务,再次访问 http://localhost/consumer/payment/hystrix/timeout/32
,测试成功。
5. 总结
两种方法各有利弊,到底使用哪一种需要根据项目情况进行判断。不过大多数情况下都是使用配置类的方式。
六、实现服务熔断
在 SpringCloud 框架里,熔断机制通过 Hystrix 实现。Hystrix 会监控微服务间调用的状态,当失败的调用到一定阈值,缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是 @HystrixCommand
在 Hystrix 中,熔断有三种状态:关闭(closed)、打开(open)、半开(half open)
如果成功访问,熔断器为关闭状态,当调用失败达到一定条件之后熔断器就会进入开启状态,开启一段时间后熔断器进入半开状态,此时如果调用成功熔断器就会进入关闭状态,如果继续调用失败,熔断器就会回到开启状态。
1. 在服务提供端添加熔断方法
在业务接口中添加熔断处理方法
// PaymentService 接口
public String paymentCircuitBreaker(Integer id);
//服务熔断
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"), //是否开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), //当在配置时间窗口内达到此数量的失败后,打开断路,默认20个
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), //断路多久以后开始尝试是否恢复,默认5s
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"), //出错百分比阈值,当达到此阈值后,开始短路。默认50%
})
public String paymentCircuitBreaker(Integer id){
//如果 id 小于 0 ,走降级方法
if (id < 0){
throw new RuntimeException("*****id 不能负数");
}
String serialNumber = IdUtil.simpleUUID();//hutool.cn工具包
return Thread.currentThread().getName()+"\t"+"调用成功,流水号:"+serialNumber;
}
public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){
return "id 不能负数,请稍候再试 id: " +id;
}
2. 在 Controller 中添加访问
@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id){
String result = paymentService.paymentCircuitBreaker(id);
log.info("*******result:"+result);
return result;
}
3. 测试
重启服务进行测试,访问 http://localhost:8001/payment/circuit/31
进行测试,结果正确
将 31 改为 -31 再次访问
连续刷新10多次后将负数改为 31 后再访问
至此,证明熔断成功。
七、服务监控 hystrixDashboard
Hystrix 提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。
1. 新建一个模块
cloud-consumer-hystrix-dashboard9001 ,同样还是以 maven 方式创建
2. 修改 POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>SpringCloudDemo</artifactId>
<groupId>org.zjh.springclouddemo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-consumer-hystrix-dashboard9001</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!--新增hystrix dashboard-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</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>
</project>
3. 创建 YML
server:
port: 9001
hystrix:
dashboard:
proxy-stream-allow-list: "*"
4. 创建启动类,添加 @EnableHystrixDashboard 注解
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApplication.class,args);
}
}
5. 所有微服务提供类(8001/8002/8003…)都需要监控依赖配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
6. 启动该微服务后将监控微服务8001
访问 http://localhost:9001/hystrix
7. 指定监控路径
新版本 Hystrix 需要在主启动类中指定监控路径,所以在 8001 端口的启动类中加入监控路径
/**
*此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
*ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
*只要在自己的项目里配置上下面的servlet就可以了
*/
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
8. 重启8001端口,观察监控窗口
输入监控路径 http://localhost:8001/hystrix.stream
9. 访问测试地址
访问之前测试熔断器的路径进行测试:
http://localhost:8001/payment/circuit/31
http://localhost:8001/payment/circuit/-31
- 实心圆:共有两种含义。它通过颜色的变化代表了实例的健康程度,它的健康度从绿色<黄色<橙色<红色递减。
该实心圆除了颜色的变化之外,它的大小也会根据实例的请求流量发生变化,流量越大该实心圆就越大。所以通过该实心圆的展示,就可以在大量的实体中快速的发现故障实例和高压力实例。- 曲线:用来记录2分钟内流量的相对变化,可以通过它来观察到流量的上升和下降趋势。