官网: https://github.com/Netflix/Hystrix/wiki/
代码地址: https://github.com/becauseoflife/CodeDemo/tree/main/SpringCloud/Hystrix/springCloud
服务雪崩
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出"、如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应"。
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒中内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
我们需要 ·弃车保帅·
10.1、什么是 Hystrix?
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
"断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个服务预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩
在分布式环境中,许多服务依赖项中的一些不可避免地会失败。Hystrix 是一个库,它通过添加延迟容错和容错逻辑来帮助您控制这些分布式服务之间的交互。Hystrix 通过隔离服务之间的访问点、停止它们之间的级联故障并提供回退选项来做到这一点,所有这些都可以提高系统的整体弹性。
Hystrix的历史
Hystrix 源于 Netflix API 团队于 2011 年开始的弹性工程工作。2012 年,Hystrix 不断发展和成熟,Netflix 内部的许多团队都采用了它。如今,Netflix 每天通过 Hystrix 执行数百亿个线程隔离和数千亿个信号量隔离调用。这极大地提高了正常运行时间和恢复能力。
10.2、Hystrix 有什么用?
Hystrix 旨在执行以下操作:
- 通过第三方客户端库访问(通常通过网络)依赖关系,保护和控制延迟和故障。
- 停止复杂分布式系统中的级联故障。
- 快速失败并迅速恢复。
- 尽可能回退并优雅降级。
- 实现近乎实时的监控、警报和操作控制。
10.3、Hystrix 解决了什么问题?
…
10.4、服务熔断
熔断机制是对应雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,**进而熔断该节点微服务的调用,快速返回错误的响应信息。**当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是 @HystrixCommand
。
实战练习
新建子模块 springcloud-provider-dept-hystrix-8001 将 springcloud-provider-dept-8001 模块复制一份。
导入Hystrix依赖
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
编写controller
/**
* 提供 restful 接口
* @author llp
* @date 2022年02月28日 15:41
*/
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@GetMapping("/dept/get/{id}")
@HystrixCommand(fallbackMethod = "hystrixGet")
public Dept get(@PathVariable("id") Long id){
Dept dept = deptService.queryDept(id);
if (dept == null){
throw new RuntimeException("id=>" + id + "不存在该用户或者找不到信息!");
}
return dept;
}
// 备选方案
public Dept hystrixGet(@PathVariable("id") Long id){
return new Dept()
.setDeptNo(id)
.setDeptName("id=>" + id + "没有对应的信息:null--@Hystrix!")
.setDbSource("no this Database in MySQL");
}
}
主启动类添加注解
@EnableCircuitBreaker // 添加对熔断的支持
启动测试,报错则将依赖 spring-cloud-starter-netflix-eureka-client
都将为 2.2.9.RELEASE
,同一每个模块中的版本。
10.5、服务降级
什么是服务降级?
当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。当整个微服务架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时,为了保证重要或基本的服务能正常运行,我们可以将一些 不重要 或 不紧急 的服务或任务进行服务的 延迟使用 或 暂停使用。
Hystrix提供的降级主要是为了容错,保证当前服务不受依赖服务故障的影响,从而提高服务的健壮性。要支持回退或降级处理,可以重写 HystrixCommand
的getFallBack()
方法或 HystrixObservableCommand
的 resumeWithFallback()
方法。
实战练习
springcloud-api 模块新增类
package com.example.springcloud.service;
import com.example.springcloud.pojo.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @desc 降级
* @auth llp
* @date 2022年03月03日 17:03
*/
@Component
public class DeptClientServiceFallBackFactory implements FallbackFactory {
public DeptClientService create(Throwable cause) {
return new DeptClientService() {
public boolean addDept(Dept dept) {
return false;
}
public Dept queryDept(Long id) {
return new Dept()
.setDeptNo(id)
.setDeptName("id=>" + id + "没有对应的信息。客户端提供了降级信息,这个服务已经被关闭!")
.setDbSource("no this Database in MySQL");
}
public List<Dept> queryAllDept() {
return null;
}
};
}
}
DeptClientService 类上的注解
@FeignClient(value = "SPRING-PROVIDER-DEPT", fallbackFactory = DeptClientServiceFallBackFactory.class)
springcloud-consumer-dept-feign 模块中添加配置
# 开启降级
#feign:
# circuitbreaker:
# enabled: true
feign:
hystrix:
enabled: true
总结:
**服务熔断:**服务端(服务提供者) 某个服务超时或者异常,引起熔断(保险丝)
**服务降级:**客户端(服务消费者) 某个网站访问负载时考虑,释放服务器资源以保证负载的核心业务有资源,保证高效稳定运行。此时客户端可以提供一个失败回调 FallbackFactory
返回一个缺省值 。
10.6、 Dashboard 流量监控
新建 springcloud-consumer-hystrix-dashboard 模块, 导入 springcloud-consumer-dept-80 模块依赖
新增依赖:
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix-dashboard -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置文件
server:
port: 9001
# Eureka 配置
eureka:
client:
register-with-eureka: false # 不向 Eureka 注册自己
主启动类
/**
* @desc
* @auth llp
* @date 2022年03月03日 17:49
*/
@SpringBootApplication
// 开启监控 Dashboard
@EnableHystrixDashboard
public class DeptConsumerDashboard_9001 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerDashboard_9001.class, args);
}
}
springcloud-provider-dept-hystrix-8001 主启动类
/**
* @desc
* @auth llp
* @date 2022年03月03日 15:25
*/
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient // 服务发现
@EnableCircuitBreaker // 添加对熔断的支持
public class HystrixDeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(HystrixDeptProvider_8001.class, args);
}
// 增加一个 Servlet
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
// 一启动就加载
registrationBean.setLoadOnStartup(1);
// 添加url
registrationBean.addUrlMappings("/actuator/hystrix.stream");
// 设置名称
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
}
启动测试
先访问: http://localhost:8001/dept/get/1 在访问: http://192.168.31.133:8001/actuator/hystrix.stream
可以看到界面一直在 ping
的数据打印
访问: http://localhost:9001/hystrix 进行监控
监控界面报错 : Unable to connect to Command Metric Stream.
在 springcloud-consumer-hystrix-dashboard (9001)的配置文件中增加 (如果 springcloud-provider-dept-hystrix-8001 中配置了 eureka.instance.prefer-ip-address: true
则使用访问的URL地址,没有配置则使用 localhost
)
hystrix:
dashboard:
proxy-stream-allow-list: "192.168.31.133"
# proxy-stream-allow-list: "localhost"
# proxy-stream-allow-list: "*"
访问地址: http://192.168.31.133:8001/dept/get/1
可以进行监控: