6. Netflix.Hystrix
6.1 简介
● 扇出
多服务之间调用,若微服务 A 调用微服务 B 和微服务 C,微服务 B 和 微服务 C 又调用其他微服务,这就是扇出
● 服务雪崩
若扇出的链路上某个微服务的调用响应时间过长或者不可用,么此扇出链路的调用就会占用越来越多的系统资源,进而引起系统崩溃,这就是雪崩效应
● 断路器
断路器是一种开关装置,当某个服务单元发生故障时,断路器的故障监控(类似熔断保险丝)会向服务调用方返回一个服务预期的,可处理的备选响应(FallBack),而不是长时间等待或者抛出调用方法无法处理的异常,这样就可以保证服务调用方的线程不会被长时间、不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
● 服务降级
服务降级一般是指在服务器压力剧增的时候,根据实际业务使用情况以及流量,对一些服务和页面有策略的不处理或者用一种简单的方式进行处理,从而释放服务器资源的资源以保证核心业务的正常高效运行。
● 服务熔断
服务熔断是应对系统服务雪崩的一种保险措施,是一种特殊降级措施。
服务熔断是服务降级的一种特殊情况,他是防止服务雪崩而采取的措施。 系统发生异常或者延迟或者流量太大,都会触发该服务的服务熔断措施,链路熔断,返回兜底方法。 这是对局部的一种保险措施。在 SpringCloud 框架中,熔断机制通常使用 Hystrix 实现。
● 什么是 Hystrix
Hystrix 是一个用于处理分布式系统的延迟和容错的开源库,能保证某个依赖出问题的情况下,不使整体服务失败,避免级联故障,提高分布式系统的弹性。
官方文档:Home · Netflix/Hystrix Wiki (github.com)
翻译文档:Hystrix 使用手册 | 官方文档翻译 - 闪客sun - 博客园 (cnblogs.com)
● Hystrix 能干什么
-
服务降级
-
服务熔断
Hystrix 监控微服务间的调用状况,当失败的调用到一定阈值,缺省为5秒内20次调用失败就会启动熔断机制,熔断机制的注解是 @HystrixCommand
-
服务限流
-
接近实时的监控
…
6.2 实现服务熔断
调整 springcloud-provider-dept-8001 服务
● 新建 maven module
将 springcloud-provider-dept-8001 服务复制到本服务,修改相关配置
● 添加依赖
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
● 修改控制层
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@GetMapping("/dept/getDept/{id}")
// 此函数执行失败后指定跳转函数
@HystrixCommand(fallbackMethod = "hystrixGetDept")
public Dept getDept(@PathVariable("id") Long id) {
Dept dept = deptService.queryById(id);
if (dept == null) throw new RuntimeException("id = " + id + " => 用户不存在");
return dept;
}
/**
* 备选方法
* @param id 用户编号
* @return 返回 Dept 对象,其 dname 为提示信息
*/
public Dept hystrixGetDept(@PathVariable("id") Long id) {
return new Dept()
.setDeptno(id)
.setDname("@hystrix id = " + id + " => 用户不存在")
.setDb_source("no this data in database");
}
}
● 开启熔断支持
// 服务启动后注册到 eureka 注册中心
@EnableEurekaClient
// 服务发现
@EnableDiscoveryClient
// 熔断支持
@EnableCircuitBreaker
@SpringBootApplication
public class HystrixDeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(HystrixDeptProvider_8001.class, args);
}
}
查询数据库内不存在的数据
6.3 实现服务降级
● 创建后备工厂
在公共服务 springcloud-api 中定义后备工厂,即服务无法调用或调用失败后的备用方法
package com.why.springcloud.service;
import com.why.springcloud.pojo.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 服务降级
*
* @author why
* @since 2021/9/9 20:56
*/
@Component
public class DeptClientFallbackFactory implements FallbackFactory {
@Override
public DeptClientService create(Throwable throwable) {
return new DeptClientService() {
@Override
public Dept queryById(Long id) {
return new Dept()
.setDeptno(id)
.setDname("@hystrix id = " + id + " => 此服务已关闭")
.setDb_source("this service has stopped");
}
@Override
public List<Dept> queryAll() {
return null;
}
@Override
public boolean addDept(Dept dept) {
return false;
}
};
}
}
● Feign 绑定后备工厂
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT", fallbackFactory = DeptClientFallbackFactory.class)
● 消费端开启 feign.hytrix
# feign.hystrix
feign:
hystrix:
enabled: true
关闭服务,再次访问
6.4 实现服务监控
(1) 新建 dashboard 服务模块
(2) 导入依赖
<!--实体类 + web-->
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
(3) 应用配置文件
server:
port: 9001
# 避免 Cannot execute request on any known server 异常
eureka:
client:
# 是否将自己注册到 Eureka-Server 中,默认为 true
# registerWithEureka等同于register_with_eureka
register-with-eureka: false
# 是否需要拉取服务信息,默认为 true
# fetchRegistry等同于 fetch-registry
fetch-registry: false
(4) 启动类开启监控
@SpringBootApplication
// 开启监控页面
@EnableHystrixDashboard
public class DeptConsumerDashboard_9001 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerDashboard_9001.class, args);
}
}
(5) 访问监控页面
localhost:9001/hystrix
(5) 服务端添加 servlet
springcloud-provider-dept-hystrix-8001
// HystrixDeptProvider_8001.java
@Bean
public ServletRegistrationBean<HystrixMetricsStreamServlet> hystrixMetricsStreamServlet() {
ServletRegistrationBean<HystrixMetricsStreamServlet> registrationBean = new ServletRegistrationBean<>(new HystrixMetricsStreamServlet());
registrationBean.addUrlMappings("/actuator/hystrix.stream");
return registrationBean;
}
(6) 访问监控页面
启动 springcloud-consumer-hystrix-dashboard
启动 springcloud-provider-dept-hystrix-8001
启动 springcloud-eureka-7001
向服务 springcloud-provider-dept-hystrix-8001 发送一个 get 请求
查看服务 springcloud-provider-dept-hystrix-8001 的流情况
填写监控页面信息
- 实心圆
- 颜色表示实例的健康状况, 绿色<黄色<橙色<红色
- 面积表示实例的请求流量,面积越大,流量越大
- 实线
- 记录两分钟内流量的相对变化