0
点赞
收藏
分享

微信扫一扫

服务降级(服务断路器)-Hystrix的介绍和使用

犹大之窗 2022-02-18 阅读 21

1 概述
1)服务雪崩是啥?
在这里插入图片描述
2)Hystrix介绍
在这里插入图片描述
3)Hystrix能干啥?
1,服务降级(fallback)
比如当某个服务繁忙,不能让客户端的请求一直等待,应该立刻返回给客户端一个备选方案
2,服务熔断(break)
当某个服务出现问题,卡死了,不能让用户一直等待,需要关闭所有对此服务的访问,然后调用服务降级
详细讲解:
类似于保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回优好提示,相当于->服务降级->进而熔断->恢复调用链路
比如并发达到1000,我们就拒绝其他用户访问,在有用户访问,就访问降级方法
在这里插入图片描述

3,服务限流(flowlimit)
限流,比如秒杀场景,不能访问用户瞬间都访问服务器,限制一次只可以有多少请求

2 服务降级使用
1,服务端降级
1)架包

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
  1. 启动类添加注解@EnableCircuitBreaker
@SpringBootApplication
@EnableCircuitBreaker
public class PaymentHystrixApplication {
    public static void main(String[] args) {
        SpringApplication.run(PaymentHystrixApplication.class, args);
        System.out.println("启动成功");
    }
}

3)接口添加@HystrixCommand

 /**
     * 超时访问,设置自身调用超时的峰值,峰值内正常运行,超过了峰值需要服务降级 自动调用fallbackMethod 指定的方法
     * 超时异常或者运行异常 都会进行服务降级
     * 设置请求是1.5秒,但是接口请求是3秒
     */
    @HystrixCommand(fallbackMethod = "paymentInfoTimeOutHandler", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
    })
    public String paymentInfoTimeOut(Integer id) {
//        int age = 10/0;//程序异常时降级
        int second = 3000;
        try {
            TimeUnit.MILLISECONDS.sleep(second);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "线程池:  " + Thread.currentThread().getName() + " paymentInfoTimeOut,id:  " + id + "\t"
                + "O(∩_∩)O哈哈~" + "  耗时(秒): " + second;
    }

    /**
     * paymentInfoTimeOut 方法失败后 自动调用此方法 实现服务降级 告知调用者 paymentInfoTimeOut 目前无法正常调用
     */
    public String paymentInfoTimeOutHandler(Integer id) {
        return "线程池:  " + Thread.currentThread().getName() + "  paymentInfoTimeOutHandler8001系统繁忙或者运行报错,请稍后再试,id:  " + id + "\t"
                + "o(╥﹏╥)o";
    }

4)运行结果
在这里插入图片描述
2 客户端降级(一般降级处理都放在客户端)

1)架包

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

2)配置

feign:
  hystrix:
    enabled: true #如果处理自身的容错就开启

3)启动类添加注解

@EnableHystrix

4 业务类代码
方法一:controller中直接控制

GetMapping("/payment/hystrix/timeout/{id}")
    @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
    })
    public String paymentInfoTimeOut(@PathVariable("id") Integer id) {
        int age = 10 / 0;
        String result = paymentHystrixService.paymentInfoTimeOut(id);
        return result;
    }

    /**
     * 超时访问,设置自身调用超时的峰值,峰值内正常运行,超过了峰值需要服务降级 自动调用fallbackMethod 指定的方法
     * <br/>
     * 超时异常或者运行异常 都会进行服务降级
     *
     */
    public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {
        return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
    }

方法二:针对方法一重复代码多

    @GetMapping("/payment/hystrix/timeout/{id}")
//    @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod", commandProperties = {
//            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
//    })
    @HystrixCommand
    public String paymentInfoTimeOut(@PathVariable("id") Integer id) {
        int age = 10 / 0;
        String result = paymentHystrixService.paymentInfoTimeOut(id);
        return result;
    }

并在controller上添加一个注解

@DefaultProperties(defaultFallback = "paymentTimeOutGlobalFallbackMethod")
public class OrderHystrixController {}

在controller中把这个全局方法写出来
public String paymentTimeOutGlobalFallbackMethod() {
        return "我是消费者80全局异常稍后处理";
    }
    

方法三 直接提出来公共的处理异常类,这样方便处理每一个接口异常返回信息,解耦

编写公共类
@Component
public class PaymentFallbackServiceImpl implements PaymentHystrixService {

    @Override
    public String paymentInfoOK(Integer id) {
        return "-----服务宕机了";
    }
}
更改PaymentHystrixService的注解
@Component
// FeignFallback 客户端的服务降级 针对 provider-payment-hystrix该服务 提供了一个 对应的服务降级类
@FeignClient(value = "PROVIDER-PAYMENT-HYSTRIX", fallback = PaymentFallbackServiceImpl.class)
public interface PaymentHystrixService {

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

注意:该方法(第三种方法)只有在运行超时(例如服务端出现高并发,宕机),兜底方法才会执行,出现运行时异常则不会执行兜底方法。
如果需要兼顾到运行时异常需要采用第1,2种方法。

3 服务熔断使用

 /**
     * 服务熔断 超时、异常、都会触发熔断
     * 1、默认是最近10秒内收到不小于10个请求,<br/>
     * 2、并且有60%是失败的<br/>
     * 3、就开启断路器<br/>
     * 4、开启后所有请求不再转发,降级逻辑自动切换为主逻辑,减小调用方的响应时间<br/>
     * 5、经过一段时间(时间窗口期,默认是5秒),断路器变为半开状态,会让其中一个请求进行转发。<br/>
     * &nbsp;&nbsp;5.1、如果成功,断路器会关闭,<br/>
     * &nbsp;&nbsp;5.2、若失败,继续开启。重复4和5<br/>
     *
     * @param id
     * @return
     */
    @HystrixCommand(fallbackMethod = "paymentCircuitBreakerFallback", commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),/* 是否开启断路器*/
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),// 请求次数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), // 时间窗口期
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")// 失败率达到多少后跳闸
    })
    public String paymentCircuitBreaker(Integer id) {
        if (id < 0) {
            throw new RuntimeException("******id 不能负数");
        }
        return Thread.currentThread().getName() + "\t" + "调用成功,流水号: " + UUID.randomUUID();
    }


    /**
     * paymentCircuitBreaker 方法的 fallback,<br/>
     * 当断路器开启时,主逻辑熔断降级,该 fallback 方法就会替换原 paymentCircuitBreaker 方法,处理请求
     *
     * @param id
     * @return
     */
    public String paymentCircuitBreakerFallback(Integer id) {
        return Thread.currentThread().getName() + "\t" + "id 不能负数或超时或自身错误,请稍后再试,/(ㄒoㄒ)/~~   id: " + id;
    }

在这里插入图片描述
断路器的打开和关闭,是按照一下5步决定的
1,并发此时是否达到我们指定的阈值
2,错误百分比,比如我们配置了60%,那么如果并发请求中,10次有6次是失败的,就开启断路器
3,上面的条件符合,断路器改变状态为open(开启)
4,这个服务的断路器开启,所有请求无法访问(即使上边接口不输入负数,还是返回了fallback方法)
5,在我们的时间窗口期,期间,尝试让一些请求通过(半开状态),如果请求还是失败,证明断路器还是开启状态,服务没有恢复
如果请求成功了,证明服务已经恢复

4 Hystrix 所有配置属性

可在HystrixCommandProperties 这个类中查看

5 Hystrix 服务监控

利用 HystrixDashboard 实现监控

在这里插入图片描述

单独创建一个工程作为Hystrix 服务监控
1)架包

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

2) 要有springboot的监控组件

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

3)启动类 添加@EnableHystrixDashboard

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {

    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardApplication.class, args);
        System.out.println("启动成功");

    }

}

4)在需要监控的服务的启动类中添加

 /**
     * 注意:新版本Hystrix需要在主启动类中指定监控路径
     * 此配置是为了服务监控而配置,与服务容错本身无关,spring cloud升级后的坑
     * ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
     * 只要在自己的项目里配置上下面的servlet就可以了
     *
     * @return ServletRegistrationBean
     */
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);

        // 一启动就加载
        registrationBean.setLoadOnStartup(1);
        // 添加url
        registrationBean.addUrlMappings("/hystrix.stream");
        // 设置名称
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

4)服务启动后指定要监控那个服务
在这里插入图片描述

请求后会看到如下图
在这里插入图片描述实心圆有两种含义:
颜色代表实例的健康程度,绿色<黄色<橙色<红色递减
请求两越大实心圆越大
通过实心圆可在大量实例中快速发现故障实例和高压力实例

曲线用来记录两分钟内流量的相对变化,通过它观察流量的上升和下降趋势
在这里插入图片描述
在这里插入图片描述

举报

相关推荐

0 条评论