Spring Cloud Hystrix:服务容错保护

Spring Cloud Hystrix:服务容错保护

 

 

1、简介

Spring Cloud Hystrix 是Spring Cloud Netflix 子项目的核心组件之一,具有服务容错及线程隔离等一系列服务保护功能,本文将对其用法进行详细介绍。

在微服务架构中,服务与服务之间通过远程调用的方式进行通信,一旦某个被调用的服务发生了故障,其依赖服务也会发生故障,此时就会发生故障的蔓延,最终导致系统瘫痪。Hystrix实现了断路器模式,当某个服务发生故障时,通过断路器的监控,给调用方返回一个错误响应,而不是长时间的等待,这样就不会使得调用方由于长时间得不到响应而占用线程,从而防止故障的蔓延。Hystrix具备服务降级、服务熔断、线程隔离、请求缓存、请求合并及服务监控等强大功能。

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。

     “断路器”本身是一种开关装置,当某个服务单元发生故障时,通过断路器的故障监控(类似熔断保险丝)向调用方返回一个符合预期的、可处理的备选响应,而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间的占用、从而避免了故障在分布式系统的蔓延。

2、使用:

2.1、maven依赖:

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

 2.2、在启动类上添加 @EnableCircuitBreaker 来开启Hystrix的断路器功能

@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class HystrixServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(HystrixServiceApplication.class, args);
    }

 

2.3、服务降级演示

@HystrixCommand(fallbackMethod = "getDefaultUser")
public CommonResult getUser(Long id) {
    return restTemplate.getForObject(userServiceUrl + "/user/{1}", CommonResult.class, id);
}

public CommonResult getDefaultUser(@PathVariable Long id) {
    User defaultUser = new User(-1L, "defaultUser", "123456");
    return new CommonResult<>(defaultUser);
}

@HystrixCommand 中的常用参数:

  • fallbackMethod:指定服务降级处理方法;
  • ignoreExceptions:忽略某些异常,不发生服务降级;
  • commandKey:命令名称,用于区分不同的命令;
  • groupKey:分组名称,Hystrix会根据不同的分组来统计命令的告警及仪表盘信息;
  • threadPoolKey:线程池名称,用于划分线程池。

 

3、如何配置全局服务降级处理?

@DefaultProperties(defaultFallBack = “”)

对于上面每一个方法都配置一个服务降级的方法,技术上可以,但是实现上傻

除了个别的业务有专属的降级方法,其他普通的通过@DefaultProperties(defaultFallBack = “”)统一一个降级方法。

通用的和独享的分开,避免了代码膨胀,合理减少代码量。

 

 4、服务降级解耦(feign的使用方式):

如果使用feign调用服务需要在yml中开启Hystrix:

  # 使feign 启用hystrix
feign:
  hystrix:
    enabled: true
@Component
@FeignClient(value = "CLOUD-HYSTRIX-PROVIDER-PAYMENT", fallback = PaymentFallBackServiceImpl.class)
public interface IPaymentHystrixServcie {

    @GetMapping("payment/hystrix/ok/{id}")
    public String paymentInfo(@PathVariable("id") Integer id);

    @GetMapping("payment/hystrix/timeout/{id}")
    public String paymentInfo_timeout(@PathVariable("id") Integer id);

}
@Component
public class PaymentFallBackServiceImpl implements IPaymentHystrixServcie {

    @Override
    public String paymentInfo(Integer id) {
        return "PaymentFallBackServiceImpl...paymentInfo_ok ,请稍后再试";
    }

    @Override
    public String paymentInfo_timeout(Integer id) {
        return "PaymentFallBackServiceImpl。。。paymentInfo_timeout,请稍后再试";
    }
}

 

5、熔断机制概述:

     熔断机制是应对雪崩效应的一种微服务链路保护机制,当扇出链路的某个微服务不可用时或者响应的时间太长,会进行服务的降级,进而熔断该微服务的调用,快熟响应错误的信息。

当检测到该节点微服务调用响应正常后,恢复调用链路。

在springCloud框架里,熔断机制是通过Hystrix实现,Hystrix会监控微服务间的调用状态。

当失败调用到一定的阀值的时候,缺省是10秒内20次请求有10次调用失败(50%),就会启动熔断机制,熔断机制的注解是@HystrixCommand.

// ##########服务熔断##########################

    @HystrixCommand(
            fallbackMethod = "paymentCircuitBreaker_fallBack", commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"), // 是否开启断路器(默认是开启的)
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"), // 请求次数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000"), // 时间窗口期
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"), // 失败率达到多少跳闸
    }
    )
@GetMapping("payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable Integer id)

涉及到断路器的三个重要参数:

1:快照时间窗sleepWindowInMilliseconds:断路器确定是否打开需要统计的一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒。

2:请求总阀值requestVolumeThreshold:在快照的时间内,必须满足请求总阀值才有资格熔断,默认是20,意味着在10秒内,如果该hystrix命令的调用次数不足20次,即使所有的请求都失败,断路器都不会断开。

3:错误百分百阀值errorThresholdPercentage:当请求总数在快照时间窗内超过了阀值,并且错误率达到默认的50%这个时候就会将断路器断开。

 Hystrix断路器默认10秒内20个请求失败率超过50%,则断路器将会开启,当开启的时候所有的请求都不会进行转发,一段时间后(默认是5秒),这个时候断路器半开的状态,会让其中 的一个请求进行转发,如果成功,断路器会关闭,如失败继续开启,直到有请求能成功为止。

配置信息(default或HystrixCommandKey)

 如: // 超时时间,默认是1000(1秒)

@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
参数 描述 默认值
execution.isolation.strategy

隔离策略,有THREAD和SEMAPHORE

THREAD - 它在单独的线程上执行,并发请求受线程池中的线程数量的限制
SEMAPHORE - 它在调用线程上执行,并发请求受到信号量计数的限制

默认使用THREAD模式,以下几种场景可以使用SEMAPHORE模式:

只想控制并发度

外部的方法已经做了线程隔离

调用的是本地方法或者可靠度非常高、耗时特别小的方法(如medis)

execution.isolation.thread.timeoutInMilliseconds 超时时间

默认值:1000

在THREAD模式下,达到超时时间,可以中断

在SEMAPHORE模式下,会等待执行完成后,再去判断是否超时

execution.timeout.enabled HystrixCommand.run()执行是否应该有超时。 默认值:true
execution.isolation.thread.interruptOnTimeout 在发生超时时是否应中断HystrixCommand.run()执行。

默认值:true

THREAD模式有效

execution.isolation.thread.interruptOnCancel 当发生取消时,执行是否应该中断

默认值为false

THREAD模式有效

execution.isolation.semaphore.maxConcurrentRequests 设置在使用时允许到HystrixCommand.run()方法的最大请求数。

默认值:10

SEMAPHORE模式有效

fallback.isolation.semaphore.maxConcurrentRequests 设置从调用线程允许HystrixCommand.getFallback()方法的最大请求数

SEMAPHORE模式有效

默认值:10

fallback.enabled 确定在发生失败或拒绝时是否尝试调用HystrixCommand.getFallback()。 默认值为true
circuitBreaker.enabled 确定断路器是否用于跟踪运行状况和短路请求(如果跳闸)。 默认值为true
circuitBreaker.requestVolumeThreshold 熔断触发的最小请求个数/10s 默认值:20
circuitBreaker.sleepWindowInMilliseconds 熔断多少秒后去尝试请求 默认值:5000
circuitBreaker.errorThresholdPercentage 失败率达到多少百分比后熔断

默认值:50

主要根据依赖重要性进行调整

circuitBreaker.forceOpen 属性如果为真,强制断路器进入打开(跳闸)状态,其中它将拒绝所有请求。

默认值为false

此属性优先于circuitBreaker.forceClosed

circuitBreaker.forceClosed 该属性如果为真,则迫使断路器进入闭合状态,其中它将允许请求,而不考虑误差百分比。

默认值为false

如果是强依赖,应该设置为true

circuitBreaker.forceOpen属性优先,因此如果forceOpen设置为true,此属性不执行任何操作。

metrics.rollingStats.timeInMilliseconds 此属性设置统计滚动窗口的持续时间(以毫秒为单位)。对于断路器的使用和发布Hystrix保持多长时间的指标。 默认值:10000
metrics.rollingStats.numBuckets

此属性设置rollingstatistical窗口划分的桶数。

以下必须为true - “metrics.rollingStats.timeInMilliseconds%metrics.rollingStats.numBuckets == 0” -否则将抛出异常。

默认值:10
metrics.rollingPercentile.enabled 此属性指示是否应以百分位数跟踪和计算执行延迟。 如果禁用它们,则所有摘要统计信息(平均值,百分位数)都将返回-1。 默认值为true
metrics.rollingPercentile.timeInMilliseconds 此属性设置滚动窗口的持续时间,其中保留执行时间以允许百分位数计算,以毫秒为单位。 默认值:60000
metrics.rollingPercentile.numBuckets

此属性设置rollingPercentile窗口将划分的桶的数量。

以下内容必须为true - “metrics.rollingPercentile.timeInMilliseconds%metrics.rollingPercentile.numBuckets == 0” -否则将抛出异常。

默认值:6
metrics.rollingPercentile.bucketSize 此属性设置每个存储桶保留的最大执行次数。如果在这段时间内发生更多的执行,它们将绕回并开始在桶的开始处重写。 默认值:100
metrics.healthSnapshot.intervalInMilliseconds 此属性设置在允许计算成功和错误百分比并影响断路器状态的健康快照之间等待的时间(以毫秒为单位)。 默认值:500

 

6、Hystrix dashboard仪表盘监控

1、maven 依赖:

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

所有的Provider微服务的提供者pom都需要依赖(actuator监控信息完善)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

 2、注解启动类

@EnableHystrixDashboard注解启动类

 yml配置端口:

server:
  port: 9001

访问localhost:9001/hystrix

 看到是上述的画面说明监控平台搭建成功。

在被监控的微服务端,启动类中加入如下代码:

 /*
    * 此配置是为了Hystrix服务监控而配置,与服务的容错本身无关,springCloud升级后的坑,
    * ServletRegistrationBean因为SpringBoot的默认路径不是"/hystrix.stream",
    * 只要在自己的项目里配置下面的servlet就可以了
    * */
    @Bean
    public ServletRegistrationBean getServlet(){
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

 7、Hystrix的常用配置

1、全局配置

hystrix:
  command: #用于控制HystrixCommand的行为
    default:
      execution:
        isolation:
          strategy: THREAD #控制HystrixCommand的隔离策略,THREAD->线程池隔离策略(默认),SEMAPHORE->信号量隔离策略
          thread:
            timeoutInMilliseconds: 1000 #配置HystrixCommand执行的超时时间,执行超过该时间会进行服务降级处理
            interruptOnTimeout: true #配置HystrixCommand执行超时的时候是否要中断
            interruptOnCancel: true #配置HystrixCommand执行被取消的时候是否要中断
          timeout:
            enabled: true #配置HystrixCommand的执行是否启用超时时间
          semaphore:
            maxConcurrentRequests: 10 #当使用信号量隔离策略时,用来控制并发量的大小,超过该并发量的请求会被拒绝
      fallback:
        enabled: true #用于控制是否启用服务降级
      circuitBreaker: #用于控制HystrixCircuitBreaker的行为
        enabled: true #用于控制断路器是否跟踪健康状况以及熔断请求
        requestVolumeThreshold: 20 #超过该请求数的请求会被拒绝
        forceOpen: false #强制打开断路器,拒绝所有请求
        forceClosed: false #强制关闭断路器,接收所有请求
      requestCache:
        enabled: true #用于控制是否开启请求缓存
  collapser: #用于控制HystrixCollapser的执行行为
    default:
      maxRequestsInBatch: 100 #控制一次合并请求合并的最大请求数
      timerDelayinMilliseconds: 10 #控制多少毫秒内的请求会被合并成一个
      requestCache:
        enabled: true #控制合并请求是否开启缓存
  threadpool: #用于控制HystrixCommand执行所在线程池的行为
    default:
      coreSize: 10 #线程池的核心线程数
      maximumSize: 10 #线程池的最大线程数,超过该线程数的请求会被拒绝
      maxQueueSize: -1 #用于设置线程池的最大队列大小,-1采用SynchronousQueue,其他正数采用LinkedBlockingQueue
      queueSizeRejectionThreshold: 5 #用于设置线程池队列的拒绝阀值,由于LinkedBlockingQueue不能动态改版大小,使用时需要用该参数来控制线程数

 

posted @ 2020-04-07 12:46  邓维-java  阅读(477)  评论(0编辑  收藏  举报