天天看点

【Spring Cloud】-Hystrix断路器

前言

高可用相关的技术以及架构,对于大型复杂的分布式系统,是非常重要的。而高可用架构中,非常重要的一个环节,就是如何将分布式系统中的各个服务打造成高可用的服务,从而足以应对分布式系统环境中的各种各样的问题,比如服务间的调用超时,或者服务间的调用失败,避免整个分布式系统被某个服务的故障给拖垮。而要解决这些棘手的分布式系统可用性问题,就涉及到了高可用分布式系统中的很多重要的技术,包括资源隔离,限流与过载保护,熔断,优雅降级,容错,超时控制,监控运维,等等。

什么是断路器

“断路器”本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路时,“断路器”能够及时的切断故障电路,防止发生过载、发热、甚至起火等严重后果。

在分布式架构中,断路器模式的作用也是类似的,当某个服务单元发生故障(类似用电器发生短路)之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。

在Spring Cloud中使用了Hystrix 来实现断路器的功能,Hystrix能够完美的解决分布式系统架构中,打造高可用服务面临的一系列技术难题,包括资源隔离,限流与过载保护,熔断,优雅降级,容错,超时控制,监控运维等等。

雪崩效应

如果单个服务C出现问题,服务B调用服务C就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务B瘫痪。服务与服务之间的依赖性,故障会传播,那么服务A调用服务B也会瘫痪,这样会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。

如何防止血崩效应的发生

spring cloud Hystrix是防雪崩利器,主要解决方案包括服务降级、依赖隔离、服务熔断、服务监控等功能

服务降级

概念

当服务器压力剧增的时候,根据当前业务情况以及流量,对一些服务和页面有策略的降级,以此缓解服务器资源的压力以保障核心任务的正常运行,同时也保证了大部分客户能得到正常的响应。

核心

优先核心服务,给核心服务不可用或若可用

自动降级使用场景

(1)、超时降级:主要配置好超时时间和超时重试次数和机制,并使用异步机制探测回复情况

(2)、失败次数降级:主要是一些不稳定的api,当失败调用次数达到一定阀值自动降级,同样要使用异步机制探测回复情况

(3)、故障降级:比如要调用的远程服务挂掉了(网络故障、DNS故障、http服务返回错误的状态码、rpc服务抛出异常),则可以直接降级。降级后的处理方案有:默认值(比如库存服务挂了,返回默认现货)、兜底数据(比如广告挂了,返回提前准备好的一些静态页面)、缓存(之前暂存的一些缓存数据)

(4)、限流降级:当我们去秒杀或者抢购一些限购商品时,此时可能会因为访问量太大而导致系统崩溃,此时开发者会使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级;降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)。

实现

1、添加依赖

<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
           

2、启动类添加注解@EnableCircuitBreaker

3、使用@HystrixCommand注解指定回调方法,即降级方法。

@RestController
public class HystrixController {

    @GetMapping("/getProductInfoList")
    //使用hystrix 实现容错机制,请求失败后执行Back,称之为“服务降级”
    @HystrixCommand(fallbackMethod = "fallback")
    public String getProductInfoList(){
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject   ("http://127.0.0.1:8005/product/list",Arrays.asList("12222222222000"),String.class);
    }

	//回退方法
    private String fallback(){
        return "太拥挤了,请稍后再试~~";
    }
}
           

4、当目标服务出错时,会触发降级调用fallback。降级不一定就是发生在目标服务不能提供正常服务了,触发降级;也可以用到自己服务内部的降级,比如抛出一个异常,触发降级,这样的话如果并发数太高,数据库连接数太多了,就可以抛一个异常,这样来触发降级。

5、fallback也可以调用在类上,使用@DefaultProderties注解,如果在每个方法上都调用一次,会需要写多次

@RestController
@DefaultProderties(defaultFallback = "defaultFallback")
public class HystrixController {
    @GetMapping("/getProductInfoList")
    public String getProductInfoList(){
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8005/product/list",Arrays.asList("12222222222000"),String.class);

    }

    private String defaultfallback(){
        return "太拥挤了,请稍后再试~~";
    }
}
           

依赖隔离

类似于docker的舱壁模式,实现进程隔离,保证容器之间互不影响。Hystrix自动实现依赖隔离,是线程池隔离。

线程池隔离:使用一个线程池来存储当前的请求,也就是说发起请求是通过Hystrix的线程池来走的,不同的服务走不同的线程池,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求堆积入线程池队列。这种方式需要为每个依赖的服务申请线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题。但是有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理,最主要的是Hystrix自动实现了依赖隔离。

服务熔断

概念

服务熔断和保险丝的使用原理很像,保险系在电压达到一定值后,会出现保险丝为控制风险,保护电器而自动烧掉,切断电源。相应的,服务熔断一般是指软件系统中,由于某些原因使得服务出现了过载现象,为防止造成整个系统故障,从而采用的一种保护措施,所以很多地方把熔断亦称为过载保护。

熔断机制

【Spring Cloud】-Hystrix断路器

可以看到服务熔断机制有三个状态:熔断关闭,熔断打开,熔断半开。

  1. 但请求成功或者失败次数低于开关阈值时,熔断处于关闭状态;
  2. 当请求失败次数达到开关阈值,熔断器会变成变成打开状态,打开状态会设置一定时间的休眠窗,比如10秒,10秒内服务降级逻辑会成为主逻辑,10秒后,熔断器会处于半开状态;
  3. 半开状态会释放一部分请求,如果释放的请求成功,熔断器关闭,服务恢主逻辑复,如果释放的请求依然失败,熔断器继续进入打开状态,休眠期计时。

实现

@RestController
@DefaultProderties(defaultFallback = "defaultFallback")
public class HystrixController {
    //熔断设置
    @HystrixCommand(commandProperties = {
            @HystrixProerty(name="circuitbreaker.enable",value="true"),  //设置熔断
            @HystrixProerty(name="circuitbreaker.requestVolumethreshold",value="10"), //滚动窗口,熔断器最小请求次数
            @HystrixProerty(name="circuitbreaker.sleepWindowInMilliseconds",value="10000"), //休眠窗,设置10秒,休眠窗内降级逻辑执行
            @HystrixProerty(name="circuitbreaker.errorThreshouldPercentage",value="60") //熔断器开关阈值,在滚动窗口内如果失败次数高于60%,熔断器打开
    })
    @GetMapping("/getProductInfoList")
    public String getProductInfoList(@RequestParam("number") Integer number){
        if(number % 2== 0){
            return "success";
        }

        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8005/product/list",Arrays.asList("12222222222000"),String.class);
    }

    private String fallback(){
        return "太拥挤了,请稍后再试~~";
    }
}
           

熔断参数

  1. Circuit Breaker:断路器
  2. sleepWindowInMilliseconds:10s;表示10s秒的休眠时间窗,10s后休眠时间窗到期,熔断器设置为半打开状态,如果请求恢复,设置为关闭状态,如果请求没有恢复,则设置为打开状态
  3. **requestVolumethreshold:**断路器的最小请求数
  4. **errorThreshouldPercentage:**断路器打开的错误百分比条件,在时间滚动窗口中如果发生了10次调用,如果有7次是错误的,超过了60%,这个时候断路器就会设置为打开状态

demo说明

【Spring Cloud】-Hystrix断路器

熔断器工作流程图

【Spring Cloud】-Hystrix断路器

降级与熔断对比

共性

目的: 目的一致,都是从系统的可用性、可靠性着想。放了防止系统的整体缓慢甚至奔溃而采用的技术手段。

最终表现: 表现类似,最终都是给用户一种当前服务不可用或者不可达的感觉

粒度: 大多都是在服务级别,当然也有一些在持久层层面的应用

自治: 基本都是靠系统达到某一临界条件时,实现自动的降级与熔断,人工降级并不是那么稳妥。

区别

触发原因: 服务熔断一般指某个服务的下游服务出现问题时采用的手段,而服务降级一般是从整体层面考虑的。

管理目标层次: 熔断是一种框架级的处理,每一个微服务都需要。而降级一般需要对业务有层级之分,降级一般都是从外围服务开始的。

实现方式: 代码级别实现有差异

服务监控

Hystrix还提供给我们一个监控功能Hystrix-dashboard,借助hystrix-dashboard可对监控进行图形化展示,就能实时的观察我们的服务调用情况。

1、引入hystrix-dashboard依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
           

2、启动类配置@EnableHystrixDashboard注解(同时配置@EnableDiscoveryClient向注册中心注册,方便管理)

3、配置文件设置端口

server:
  port: 8087

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${server.port}
spring:
  application:
    name: hystrix-dashboard
           

4、监控界面如下

【Spring Cloud】-Hystrix断路器

继续阅读