一、简介
在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC) 。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。
Hystrix是Netflix开源的一款容错框架,同样具有自我保护能力。为了解决雪崩效应。
例子:
Hystrix整个工作流程
- 构造一个 HystrixCommand或HystrixObservableCommand对象,用于封装请求,并在构造方法配置请求被执行需要的参数;
- 执行命令,Hystrix提供了4种执行命令的方法,后面详述;
- 判断是否使用缓存响应请求,若启用了缓存,且缓存可用,直接使用缓存响应请求。Hystrix支持请求缓存,但需要用户自定义启动;
- 判断熔断器是否打开,如果打开,跳到第8步;
- 判断线程池/队列/信号量是否已满,已满则跳到第8步;
- 执行HystrixObservableCommand.construct()或HystrixCommand.run(),如果执行失败或者超时,跳到第8步;否则,跳到第9步;
- 统计熔断器监控指标;
- 走Fallback备用逻辑
- 返回请求响应
Hystrix容错
服务的熔断和降级
- 隔离:将请求封装在HystrixCommand中,然后这些请求在一个独立的线程中执行,每个依赖服务维护一个小的线程池(或信号量),在调用失败或超时的情况下可以断开依赖调用或者返回指定逻辑
- 熔断:当HystrixCommand请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务,断路器保持在开路状态一段时间后(默认5秒),自动切换到半开路状态(HALF-OPEN),这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED),否则重新切换到开路状态(OPEN)
- 降级:服务降级是指当请求后端服务出现异常的时候, 可以使用fallback方法返回的值。使用fallback返回一个友好的错误提示信息。
基本的容错模式
- 1.主动超时:Http请求主动设置一个超时时间,超时就直接返回,不会造成服务堆积
- 2.限流:限制最大并发数
- 3.熔断:当错误数超过阈值时快速失败,不调用后端服务,同时隔一定时间放几个请求去重试后端服务是否能正常调用,如果成功则关闭熔断状态,失败则继续快速失败,直接返回。(此处有个重试,重试就是弹性恢复的能力)
- 4.隔离:把每个依赖或调用的服务都隔离开来,防止级联失败引起整体服务不可用
- 5.降级:服务失败或异常后,返回指定的默认信息
Hystrix的使用
作用:断路器,保护系统,控制故障范围。
Hystrix对Feing客户端的支持:
在Order工程(服务消费者)中添加Hystrix的依赖:
<!-- 断路器的依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
[1]使用方法申明降级服务
在OrderController中添加一个降级服务。添加一个专门处理请求失败的方法。
// 降级服务调用的方法
public User queryUserByIdTimeOut(long userId){
//这里不做真实的查询 实际应用中可能返回是一个专门定义的对象,其中包含了数据,状态码,信息
User user = new User();
user.setUserId(userId);
user.setUserName("请求超时,请检查网络");
return user;
}
在OrderController的方法上方添加一个注解,注解中添加一个fallbackMethod的配置:这里的fallbackMethod就是配置服务降级的方法。
在主应用类中激活Hystrix
@EnableHystrix //激活hystrix引用
@SpringBootApplication
@EnableFeignClients //激活feign客户端
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
配置Feign的超时时间:
设置Feign的超时时间
ribbon: ReadTimeout: 2000 ConnectTimeout: 2000
修改服务提供者(Base)中的操作,模拟重操作
@RequestMapping(value = "/queryUser",produces = "application/json;charset=utf-8")
@ResponseBody
public User queryUserById(long userId){
System.out.println("Base-UserContrller-queryUserById:"+port);
User user = userService.getById(userId);
//模拟重操作
try {
Thread.sleep(1985);
} catch (InterruptedException e) {
e.printStackTrace();
}
//将端口号设置到到user的名称中
user.setUserName(user.getUserName()+"-->"+port);
return user;
}
[2]使用服务降级类。
准备一个降级服务类,实现Feign客户端接口:
/**
* @author:刘倩云
* @createTime:2021-04-08
*/
@Component
public class UserFeignFallback implements UserFeignClient {
@Override
public User queryUserById(long userId) {
//这里不做真实的查询 实际应用中可能返回是一个专门定义的对象,其中包含了数据,状态码,信息
User user = new User();
user.setUserId(userId);
user.setUserName("请求超时,请检查网络");
return user;
}
@Override
public User queryUserById1(long userId) {
//这里不做真实的查询 实际应用中可能返回是一个专门定义的对象,其中包含了数据,状态码,信息
User user = new User();
user.setUserId(userId);
user.setUserName("请求超时,请检查网络");
return user;
}
}
在UserFeignClient中配置降级服务类:
在配置文件中配置开启feign客户端的服务熔断和降级。
feign: hystrix: enabled: true #开启Feign客户端的服务熔断和降级#
去掉之前配置的服务降级配置。