3.Hystrix断路器

回眸只為那壹抹淺笑 提交于 2020-02-25 02:02:13

1.为什么需要断路器

1.1存在问题
在理想状态下,一个应用依赖的服务都是健康可用的,我们可以正常处理所有的请求。默认情况下tomcat只有一个线程池去处理的客户端发送的所有服务请求,这样在高并发情况下,如果客户端所有的请求堆积到同一个服务接口上,就会产生tomcat的所有线程池去处理该服务接口,可能会导致其他服务奔溃。
1.2简介
Hystrix,英文意思是豪猪,全身是刺,看起来就不好惹,是一种保护机制。
在这里插入图片描述
Hystrix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。
1.3雪崩效应
在复杂的微服务架构中的应用程序有很多的依赖,都会不可避免地在某些时候失败。高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险。一个请求,可能需要调用多个微服务接口才能实现,会形成非常复杂的调用链路:
在这里插入图片描述
如图,一次业务请求,需要调用A、H、I、P四个服务,这四个服务又可能调用其它服务。
如果此时某个服务出现异常:
在这里插入图片描述
例如微服务I发生异常,请求阻塞,用户不会得到响应,则tomcat的这个线程不会释放,于是越来越多的用户请求到来,越来越多的线程会阻塞:
在这里插入图片描述
服务器支持的线程和并发数有限,请求一直阻塞,会导致服务器资源耗尽,从而导致所有其它服务不可用,形成雪崩效应。
Hystrix解决雪崩问题的手段包括:

  • 线程隔离
  • 服务熔断
  • 服务降级

1.4 解决方法和原理
(1)线程隔离
资源隔离(限流):包括线程池隔离和信号量隔离,限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其他服务调用。

  • 线程池隔离模式:使用一个线程池来存储当前请求,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求先入线程池队列。这种方式要为每个依赖服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理)
  • 信号量隔离模式:使用一个原子计数器(或信号量)记录当前有多少个线程在运行,请求来先判断计数器的数值,若超过设置的最大线程个数则丢弃该类型的新请求,若不超过则执行计数操作请求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服务)

(2)服务熔断
正常情况下,断路器处于关闭状态(Closed),如果调用持续出错或者超时,电路被打开进入熔断状态(Open),后续一段时间内的所有调用都会被拒绝(Fail Fast),一段时间以后,保护器会尝试进入半熔断状态(Half-Open),允许少量请求进来尝试,如果调用仍然失败,则回到熔断状态;如果调用成功,则回到电路闭合状态;
在这里插入图片描述
Hystrix提供了如下的几个关键参数,来对一个熔断器进行配置:

  • circuitBreaker.requestVolumeThreshold //滑动窗口的大小,默认为20
  • circuitBreaker.sleepWindowInMilliseconds //过多长时间,熔断器再次检测是否开启,默认为5000,即5s
  • circuitBreaker.errorThresholdPercentage //错误率,默认50%

3个参数放在一起,所表达的意思就是:
每当20个请求中,有50%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到5s之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开。
熔断的3个状态

  • Closed:关闭状态,所有请求都正常访问
  • Open:打开状态,所有请求都会被降级。Hystrix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器会完全打开。
  • Half Open:半开状态,open状态不是永久的,打开后会进入休眠时间(默认5s)。随后断路器会自动进入半开状态,此时会释放部分请求通过,若这些请求都是健康的,则会完全关闭断路器,否则继续保持打开,再次进行休眠计时。

(3)服务降级
服务降级:优先保证核心服务,而非核心服务不可用或弱可用。
例如:当用户的请求故障时,不会被阻塞,更不会无休止的等待或者看到系统奔溃,至少可以看到一个执行结果(例如返回友好的提示信息),服务降级虽然会导致请求失败,但是不会导致阻塞,且对其它服务无响应。
触发Hystrix服务降级的情况:

  • 线程池已满
  • 请求超时

1.5 Hystrix使用
在服务消费方使用Hystrix

  • 引入坐标
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

  • application.yml
在这里插入代码片
  • 配置启动类
@EnableCircuitBreaker
public class ServiceConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceConsumerApplication.class, args);
    }
}
  • 为可能发生熔断的方法添加@HystrixCommand注解
@RestController
@RequestMapping("user")
//定义全局的熔断方法
@DefaultProperties(defaultFallback = "queryUserByIdFallBack")
public class UserController {
    
    @GetMapping("get/{id}")
    @HystrixCommand
    public String queryUserById(@PathVariable Long id){
        return "请求的id:"+id;
    }

    public String queryUserByIdFallBack(Long id){
        return "服务忙,稍后再试";
    }
}

这样当user/get/{id}请求调用的远程服务不可用时,将返回fallBack回调函数的内容。
1.6设置超时
Hystrix设置的默认超时时长为1,请求在超过1秒后会返回错误信息,可以通过配置信息修改时长

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 6000 #超时时间

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!