一、简介

在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC) 。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。
Hystrix是Netflix开源的一款容错框架,同样具有自我保护能力。为了解决雪崩效应。
例子:
image.png

Hystrix整个工作流程

  1. 构造一个 HystrixCommand或HystrixObservableCommand对象,用于封装请求,并在构造方法配置请求被执行需要的参数;
  2. 执行命令,Hystrix提供了4种执行命令的方法,后面详述;
  3. 判断是否使用缓存响应请求,若启用了缓存,且缓存可用,直接使用缓存响应请求。Hystrix支持请求缓存,但需要用户自定义启动;
  4. 判断熔断器是否打开,如果打开,跳到第8步;
  5. 判断线程池/队列/信号量是否已满,已满则跳到第8步;
  6. 执行HystrixObservableCommand.construct()或HystrixCommand.run(),如果执行失败或者超时,跳到第8步;否则,跳到第9步;
  7. 统计熔断器监控指标;
  8. 走Fallback备用逻辑
  9. 返回请求响应

Hystrix容错

服务的熔断和降级

  • 隔离:将请求封装在HystrixCommand中,然后这些请求在一个独立的线程中执行,每个依赖服务维护一个小的线程池(或信号量),在调用失败或超时的情况下可以断开依赖调用或者返回指定逻辑
  • 熔断:当HystrixCommand请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务,断路器保持在开路状态一段时间后(默认5秒),自动切换到半开路状态(HALF-OPEN),这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED),否则重新切换到开路状态(OPEN)
  • 降级:服务降级是指当请求后端服务出现异常的时候, 可以使用fallback方法返回的值。使用fallback返回一个友好的错误提示信息。

基本的容错模式

  • 1.主动超时:Http请求主动设置一个超时时间,超时就直接返回,不会造成服务堆积
  • 2.限流:限制最大并发数
  • 3.熔断:当错误数超过阈值时快速失败,不调用后端服务,同时隔一定时间放几个请求去重试后端服务是否能正常调用,如果成功则关闭熔断状态,失败则继续快速失败,直接返回。(此处有个重试,重试就是弹性恢复的能力)
  • 4.隔离:把每个依赖或调用的服务都隔离开来,防止级联失败引起整体服务不可用
  • 5.降级:服务失败或异常后,返回指定的默认信息

Hystrix的使用

作用:断路器,保护系统,控制故障范围。
Hystrix对Feing客户端的支持:
在Order工程(服务消费者)中添加Hystrix的依赖:

  1. <!-- 断路器的依赖 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  5. </dependency>

[1]使用方法申明降级服务

在OrderController中添加一个降级服务。添加一个专门处理请求失败的方法。

// 降级服务调用的方法
public User queryUserByIdTimeOut(long userId){
    //这里不做真实的查询  实际应用中可能返回是一个专门定义的对象,其中包含了数据,状态码,信息
    User user = new User();
    user.setUserId(userId);
    user.setUserName("请求超时,请检查网络");
    return user;
}

在OrderController的方法上方添加一个注解,注解中添加一个fallbackMethod的配置:这里的fallbackMethod就是配置服务降级的方法。
image.png
在主应用类中激活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中配置降级服务类:
image.png
在配置文件中配置开启feign客户端的服务熔断和降级。

feign: hystrix: enabled: true #开启Feign客户端的服务熔断和降级#

去掉之前配置的服务降级配置。
image.png