Hystrix 实现服务熔断与降级

本文为博主原创,未经允许不得转载:

目录:

  1. 服务雪崩,服务熔断,服务降级概念

  2. Hystrix 概念

  3. Hystrix 使用及默认配置

  4. @HystrixCommond 注解使用

  5. 常用熔断器配置

  1. 服务雪崩,服务熔断,服务降级

     服务雪崩:因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程,就叫服务雪崩效应。如 A 服务调用 B 服务,B服务再调用C服务,

        当C服务不可用,且大量请求从 A端请求到C端时,因为C 服务不可用,会导致线程池里所有线程都因等待响应而被阻塞, 从而造成服务雪崩

      服务熔断:当下游的服务因为某种原因突然变得不可用或响应过慢,上游服务为了保证自己整体服务的可用性,不再继续调用目标服务,直接返回,

        快速释放资源。如果目标服务情况好转则恢复调用。需要说明的是熔断其实是一个框架级的处理,那么这套熔断机制的设计,基本上业内用

        的是断路器模式,与熔断器是相同的原理。

     服务降级:就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调,返回一个缺省值。

        使用场景:

          1. 当系统服务遇到双十一,大促销等场景时,可对不重要的服务进行降级,释放出服务器的资源,优先保障核心业务

          2. 当下游的服务因为某种原因不可用,上游主动调用本地的一些降级逻辑,避免卡顿,迅速返回给用户!

        服务熔断也是服务降级的一种保护措施,还包括:限流降级,开关降级

  2. Hystrix 基本概念:

    Hystrix并不是Spring的,而是NetFlix公司开源的,提供超时机制,限流,熔断,降级最全面的实现.

    原理:通过“命令模式”的方式,继承(HystrixCommand类)来包裹具体的服务调用逻辑(run方法), 并在命令模式中添加了服务调用失败后的降级逻辑(getFallback)

    资源隔离:线程隔离,信号量隔离
    线程隔离:Hystrix会给每一个Command分配一个单独的线程池,这样在进行单个服务调用的时候,就可以在独立的线程池里面进行,而不会对其他线程池造成影响
    信号量隔离:客户端需向依赖服务发起请求时,首先要获取一个信号量才能真正发起调用,由于信号量的数量有限,当并发请求量超过信号量个数时,后续的  
        请求都会直接拒绝,进入fallback流程。信号量隔离主要是通过控制并发请求量,防止请求线程大面积阻塞,从而达到限流和防止雪崩的目的。
  

  3. Hystrix 使用及默认配置

    3.1 添加 pom 依赖:

      <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--hystrix官网-->
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-core</artifactId>
            <version>1.5.18</version>
        </dependency>

        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-javanica</artifactId>
            <version>1.5.18</version>
        </dependency>

    3.2 默认配置及常用配置:

      3.2.1 线程隔离配置:

      hystrix.command.default.execution.isolation.strategy 隔离策略,默认是Thread, 可选Thread|Semaphore

      hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 命令执行超时时间,默认1000ms

      hystrix.command.default.execution.timeout.enabled 执行是否启用超时,默认启用true

      hystrix.command.default.execution.isolation.thread.interruptOnTimeout 发生超时是是否中断,默认true

       3.2.2 信号量隔离配置 

      hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests  最大并发请求数,默认10,该参数当使用

        ExecutionIsolationStrategy.SEMAPHORE策略时才有效。如果达到最大并发请求数,请求会被拒绝。理论上选择semaphore size的原则和

        选择thread size一致,但选用semaphore时每次执行的单元要比较小且执行速度快(ms级别),否则的话应该用thread。

      hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests  如果并发数达到该设置值,请求会被拒绝和抛出
        异常并且fallback不会被调用。默认10

      3.2.3 ThreadPool 相关参数

      hystrix.threadpool.default.coreSize 并发执行的最大线程数,默认10

      hystrix.threadpool.default.maxQueueSize   BlockingQueue的最大队列数,当设为-1,会使用SynchronousQueue,值为正时使用LinkedBlcokingQueue。
        该设置只会在初始化时有效,之后不能修改threadpool的queue size,除非reinitialising thread executor。默认-1。
      hystrix.threadpool.default.queueSizeRejectionThreshold 即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝。
        因为maxQueueSize不能被动态修改,这个参数将允许我们动态设置该值。if maxQueueSize == ­1,该字段将不起作用
 

  4. @HystrixCommand 的使用

    4.1 在需要熔断与降级的方法上使用 @HystrixCommand  注解

 @HystrixCommand(fallbackMethod = "onError",
            ignoreExceptions = ClassNotFoundException.class,
            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
                    @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2")},
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "5"),
                    @HystrixProperty(name = "maximumSize", value = "5"),
                    @HystrixProperty(name = "maxQueueSize", value = "10")
            })
    @RequestMapping("/sayHello")
    public String sayHello(String name) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Hello, " + name;
    }

    /**
     * 如果fallback方法的参数和原方法参数个数不一致,则会出现FallbackDefinitionException: fallback method wasn't found
     */
    public String onError(String name) {
        return "Error!!!" + name;
    }

  4.2 添加 HystrixCommand 注解使用的切面配置

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Servlet;

@Configuration
public class HystrixConfig {

    /**
     * A {@link ServletContextInitializer} to register {@link Servlet}s in a Servlet 3.0+ container.
     */
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet() {
        return new ServletRegistrationBean(new HystrixMetricsStreamServlet(), "/hystrix.stream");
    }

    /**
     * AspectJ aspect to process methods which annotated with {@link HystrixCommand} annotation.
     *
     * {@link HystrixCommand} annotation used to specify some methods which should be processes as hystrix commands.
     */
    @Bean
    public HystrixCommandAspect hystrixCommandAspect() {
        return new HystrixCommandAspect();
    }

}

  5. 常用熔断器配置

    Circuit Breaker一共包括如下6个参数。
      1、circuitBreaker.enabled
        是否启用熔断器,默认是TURE。
      2、circuitBreaker.forceOpen
        熔断器强制打开,始终保持打开状态。默认值FLASE。
      3、circuitBreaker.forceClosed
        熔断器强制关闭,始终保持关闭状态。默认值FLASE。
      4、circuitBreaker.errorThresholdPercentage
        设定错误百分比,默认值50%,例如一段时间(10s)内有100个请求,其中有55个超时或者异常返回了,那么这段时间内的错误百分比是55%,大于了默认值50%,这种情况下触发熔断器-打开。
      5、circuitBreaker.requestVolumeThreshold
        默认值20.意思是至少有20个请求才进行errorThresholdPercentage错误百分比计算。比如一段时间(10s)内有19个请求全部失败了。错误百分比是100%,但熔断器不会打开,因为requestVolumeThreshold的值是20. 这个参数非常重要,熔断器是否打开首先要满足这个条件
      6、circuitBreaker.sleepWindowInMilliseconds
        半开试探休眠时间,默认值5000ms。当熔断器开启一段时间之后比如5000ms,会尝试放过去一部分流量进行试探,确定依赖服务是否恢复。
原文地址:https://www.cnblogs.com/zjdxr-up/p/15085493.html