断路器——Hystrix
概述
分布式系统面临问题
- 多个微服务互相调用的时候,A服务调用B和C,B和C又调用其他的服务,这叫做**服务扇出**
- 如果扇出链路上某个服务响应时间过长或不可用,对A服务的调用会占用很多的系统资源,进而导致**服务雪崩**
- 复杂分布式系统中,一个微服务可能有数十个其他的服务依赖,如果其中一个服务出现问题,可能导致**服务雪崩**
Hystrix是什么?
- Hystrix是一个用于处理分布式系统延迟和容错的开源库
- Hystrix保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,提高分布式系统的弹性
断路器是什么?
- 本身是一种开关,当某个服务单元故障时,向调用方返回一个符合预期的、可处理的备选响应,而不是长时间的等待或抛出无法处理的异常,从而避免的服务故障的蔓延,有效避免雪崩
服务熔断
是什么?
- 是一种应对雪崩效应的**微服务链路保护机制**
- 当扇出链路的某个服务不可用或者响应时间过长时,进行**服务降级**,熔断该节点微服务的调用,快速返回错误的响应信息
构建带Hystrix的Provider
修改POM.XML
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
修改application.yml
eureka:
client: #客户端注册进eureka服务列表内
service-url:
# defaultZone: http://localhost:7001/eureka
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: springcloud-dept8001-hystrix
prefer-ip-address: true #访问路径可以显示IP地址
- 修改实例ID,和原本的8001 Provider区别
修改Controller
@RestController
public class DeptController {
private final DeptService service;
public DeptController(DeptService service) {
this.service = service;
}
@HystrixCommand(fallbackMethod = "processHystrix_GET")
@GetMapping(value = "/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
Dept dept = service.get(id);
if (dept==null)
throw new RuntimeException("该ID("+id+")没有对应信息");
return dept;
}
private Dept processHystrix_GET(@PathVariable("id") Long id) {
return new Dept().setDeptno(id).setDname("该ID没有对应的信息,NULL ==> @HystrixCommand").setDb_source("No This Database in Mysql");
}
}
- 添加方法来处理异常 processHystrix_GET,注意其参数和返回值要和需要处理的URL对应方法一致
- 在要进行处理的Url对应方法上添加注解**@HystrixCommand,注解参数fallbackMethod值为刚才写的处理异常方法processHystrix_GET**
修改主启动类
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableHystrix
public class DeptProvider8001Hystrix_App {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001Hystrix_App.class,args);
}
}
- 添加启用Hystrix的注解EnableHystrix
测试
- 启动eureka集群
- 启动带hystrix的provider
- 启动consumer
- 测试
- 集群启动成功,provider成功注册
- 正常访问,不出异常
- 访问数据库中没有的记录,出异常,熔断测试成功
服务降级
是什么?
- 系统资源不足了,先将某些服务关停,待度过难关,再将关停的服务启动
项目构建
在API工程中新建实现DeptClientService的DeptClientServiceFallbackFactory
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {
@Override
public DeptClientService create(Throwable cause) {
return new DeptClientService() {
@Override
public Dept get(Long id) {
return new Dept().setDeptno(id).setDname("该ID没有对应的信息,Consumer客户端提供的降级信息,此刻Provider服务已经关闭").setDb_source("No This Database in Mysql");
}
@Override
public List<Dept> list() {
return null;
}
@Override
public boolean add(Dept dept) {
return false;
}
};
}
}
- 不要忘记在类上面添加Component注解
在API工程中修改DeptClientService
//@FeignClient(value = "SPRINGCLOUD-DEPT")
@FeignClient(value = "SPRINGCLOUD-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
@GetMapping(value = "/dept/get/{id}")
Dept get(@PathVariable("id") Long id);
@GetMapping(value = "/dept/list")
List<Dept> list();
@PostMapping(value = "/dept/add")
boolean add(@RequestBody Dept dept);
}
- 在FeignClient注解添加注解属性fallbackFactory,值为DeptClientServiceFallbackFactory的类
修改带Feign的Consumer:application.yml
feign:
hystrix:
enabled: true
测试
- 启动eureka集群
- 启动8001 provider
- 启动带feign的consumer
- 测试
- 集群启动成功,8001成功注册
- 正常访问测试
- 关闭8001 provider,再访问测试
- 注意:服务降级是在客户端即consumer实现的,与服务端没有关系
服务监控HystrixDashboard
是什么?
- 提供准实时的调用监控
- 持续记录每秒成功请求多少次,失败多少次,以图形化界面展示出来
构建带dashboard的consumer
POM.XML
<dependencies>
<dependency><!-- 自己定义的api -->
<groupId>online.abor</groupId>
<artifactId>springcloud-api</artifactId>
<version>${project.version}</version>
</dependency>
<!--Feign相关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
<!-- Ribbon相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
application.yml
server:
port: 9001
主启动类
@SpringBootApplication
@EnableHystrixDashboard
public class DeptConsumer_DashBoard_App {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_DashBoard_App.class,args);
}
}
所有的provider添加依赖
<!-- actuator监控信息完善 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
启动监控微服务
- 访问http://localhost:9001/hystrix,出现豪猪代表启动成功
如何监控服务?
- 启动eureka集群
- 启动带hystrix的provider
- 访问http://localhost:8001/hystrix.stream,会持续的发出ping请求
- 在9001监控界面输入http://localhost:8001/hystrix.stream
- 新开浏览器窗口,持续访问provider