Hystirx熔断降级机制

Hystrix特性

  • 服务降级(服务提供者端):返回托底数据,避免服务雪崩
  • 熔断:当服务的失败率达到阈值时,断路器打开,自动走降级方法
  • 隔离(限流):提供独立的线程池处理微服务的调用,与本地请求的线程池隔离,同时支持线程池限流

使用Hystrix

引入依赖

        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
        dependency>

启动类上添加注解

@EnableHystrix

使用Hystrix保护接口,在接口方法上添加注解 @HystrixCommand(fallbackMethod = “fallback”),其中fallback是当接口调用发生异常时,执行的降级方法。如下两种情况都会触发降级。

  • 运行时异常
  • 超时
@SpringBootApplication
@RestController
@EnableHystrix // 启动类上要添加注解
public class Micro4App {

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

    @HystrixCommand(fallbackMethod = "fallback")
    @GetMapping("/test1")
    public String test1() throws InterruptedException {
//        int i = 1/0;
        TimeUnit.SECONDS.sleep(3);
        return "Micro4App test1";
    }

    public String fallback(){
        return "fallback : Micro4App test1 方法故障了";
    }
}

配置Hystrix的超时时间

全局配置 默认不设置是1秒

# 方法调用超过5秒则触发降级
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 5000

在某个具体的接口上,通过@HystrixCommand配置

    @HystrixCommand(fallbackMethod = "fallback",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "2000")
    })
    @GetMapping("/test1")
    public String test1() throws InterruptedException {
//        int i = 1/0;
        TimeUnit.SECONDS.sleep(3);
        return "Micro4App test1";
    }

断路器

马丁福勒断路器论文:https://martinfowler.com/bliki/CircuitBreaker.html

在调用指定服务时,如果说这个服务的失败率达到你输入的一个阈值,将断路器从closed状态,转变为open状态,指定服务是无法被访问的,如果你访问就直接走fallback方法,在一定的时间内,open状态会再次转变为half open状态,允许一个请求发送到我的指定服务,如果成功,转变为closed,如果失败,服务再次转变为open状态,会再次循环到half open,直到断路器回到一个closed状态。

Hystirx熔断降级机制_第1张图片

配置断路器的监控界面

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboardartifactId>
dependency>

启动类中加注解

@EnableHystrixDashboard

开启Hystirx的监控Servlet,用于提供监控数据

@WebServlet("/hystrix.stream")
public class HystrixServlet extends HystrixMetricsStreamServlet {
}

//------------------------------------------------------------
// 在启动类上,添加扫描Servlet的注解
@ServletComponentScan("com.qf.servlet")

配置文件中设置允许监控localhost

hystrix:
  dashboard:
    proxy-stream-allow-list: localhost

测试直接访问http://host:port/hystrix 他只监控加了 降级的 方法

Hystirx熔断降级机制_第2张图片

Hystirx熔断降级机制_第3张图片
断路器的属性(默认10s秒中之内至少有20个请求,50%的请求出现异常或超时,断路器开。)

配置信息 name value
断路器的开关 circuitBreaker.enabled true
至少有20个请求才进行errorThresholdPercentage错误百分比计算 circuitBreaker.requestVolumeThreshold 20
请求总数失败率达到%多少时 circuitBreaker.errorThresholdPercentage 50
断路器open状态后,多少秒是拒绝请求的 circuitBreaker.sleepWindowInMilliseconds 5000
强制让服务拒绝请求 circuitBreaker.forceOpen false
强制让服务接收请求 circuitBreaker.forceClosed false
    @GetMapping("/test2/{flag}")
    @HystrixCommand(fallbackMethod = "test2fallback",commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "70"),
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "5000")
    })
    public String test2(@PathVariable("flag") String flag) throws InterruptedException {

        System.out.println("进入test2 方法了。。。。");
        if (flag.equals("1")){
            int i = 1/0;
        }
        System.out.println(Thread.currentThread().getName());
        return "test2 ok";
    }
 //fallbackMethod 中设置的是降级方法的名字
    @GetMapping("/test1")
    @HystrixCommand(fallbackMethod = "test1fallback",commandProperties = {
          //设置该接口的超时时间,一旦超时返回降级方法中的结果
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "2000")
    })//加了这个注解超时时间不超过1秒,超过就降级
    public String test1() throws InterruptedException {
        System.out.println("test还没熔断");
        int a=1/0;

//        Thread.sleep(3000);
       return "hello hystrix";
    }



    public String test1fallback() throws InterruptedException{
        System.out.println("-------------");
        return "test1()降级方法返回的数据";
    }

限流(隔离)

Hystrix通过线程池配置可以进行请求限流。

  • 可以指定请求运行线程池(独立于tomcat的线程池)
  • 可以指定线程池的线程数量和等待队列大小
  • 当请求并发数量超过线程数量+队列大小后,请求进入降级方法
    @GetMapping("/test3")
    @HystrixCommand(
            fallbackMethod = "fallback",
            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
            },
            threadPoolKey = "mypool",
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "5"),
                    @HystrixProperty(name = "maxQueueSize", value = "5")
            }
    )
    public String test3() throws InterruptedException {
        System.out.println(Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(1);
        return "test3 ok";
    }

    @GetMapping("/tt/{num}")
    public String tt(@PathVariable("num") Integer num) throws InterruptedException {
        RestTemplate restTemplate = new RestTemplate();

        CountDownLatch countDownLatch = new CountDownLatch(num);

        for (int i=0;i<num;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String s = restTemplate.getForObject("http://localhost:9300/test3", String.class);
                    System.out.println(Thread.currentThread().getName()+s);
                    countDownLatch.countDown();
                }
            }).start();
        }

        countDownLatch.await();
        return "ok";

    }

自己: 限流超出的请求不会 开启 断路器 ,不记录失败数!

 @GetMapping("/test2")
    public String test2(){
        System.out.println("处理请求的线程名字为"+Thread.currentThread().getName());
        return Thread.currentThread().getName();
    }


    @GetMapping("/test3")
    /**
     * 限制 test3的最大并发度为10 ,即最多可以同时处理10个请求,
     * 超出的请求会被降级
     * @return
     */
    @HystrixCommand(fallbackMethod = "test3fallback",
    threadPoolKey = "mypool",
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "5"),
                    @HystrixProperty(name = "maxQueueSize", value = "5")
            }
    )
    public String test3(){
        System.out.println("处理请求的线程名字为"+Thread.currentThread().getName());
        return Thread.currentThread().getName();
    }

    public String test3fallback(){
        return "这是test3的降级方法";
    }

}

你可能感兴趣的:(java,开发语言)