Hystirx熔断降级机制

Hystrix特性

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

使用Hystrix

引入依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </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状态。

在这里插入图片描述

配置断路器的监控界面

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</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 他只监控加了 降级的 方法

在这里插入图片描述

在这里插入图片描述
断路器的属性(默认10s秒中之内至少有20个请求,50%的请求出现异常或超时,断路器开。)

配置信息namevalue
断路器的开关circuitBreaker.enabledtrue
至少有20个请求才进行errorThresholdPercentage错误百分比计算circuitBreaker.requestVolumeThreshold20
请求总数失败率达到%多少时circuitBreaker.errorThresholdPercentage50
断路器open状态后,多少秒是拒绝请求的circuitBreaker.sleepWindowInMilliseconds5000
强制让服务拒绝请求circuitBreaker.forceOpenfalse
强制让服务接收请求circuitBreaker.forceClosedfalse
    @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的降级方法";
    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值