Hystrix原理及其使用

目录

1、概念

1.1、分布式系统面临的问题

1.2、Hystrix是什么

1.3、Hystrix作用

1.4、Hystrix工作流程

2、Hystrix案例

2.1、构建正常微服务(服务提供者)

2.2、压力测试

2.2.1、Jmeter压测测试

2.2.2、客户端压测测试

3、解决方案

3.1、服务降级

3.1.1、服务端微服务降级

3.1.2、客户端微服务降级

3.1.3、代码优化

4、服务熔断

4.1、熔断概念

4.2、熔断实操(服务端微服务)

4.2.1、service层

 4.2.2、controller层

4.3、 熔断原理

4.3.1、熔断类型

4.3.2、断路器流程

5、服务监控Hystrix Dashboard

5.1、Hystrix Dashboard概述

5.2、Hystrix Dashboard服务搭建

5.2.1、POM文件:

5.2.2、 配置yaml文件(端口号)

5.2.3、编写主启动类

5.2.4、 访问http://localhost:9001/hystrix,得到以下页面

5.3、断路器演示(9001监控8001)

5.3.1、填写监控地址 http://localhost:8001/hystrix.stream

5.3.2、多次调用微服务,并在监控界面打开Monitor stream


1、概念

1.1、分布式系统面临的问题

1.分布式体系结构中的应用程序,有数10个依赖关系,每个依赖关系在某些时候将不可避免的失败

2.服务雪崩:

  • 多个微服务之间调用时,假设微服务A调用微服务B和C,B和C又调用其他微服务,即“扇出”。
  • 扇出的链路上某个微服务的调用响应时间过长或不可用,对A的调用会占用越来越多的系统资源,进而引起系统崩溃(级联故障),即“雪崩效应

1.2、Hystrix是什么

 1.Hystrix是一个用于处理分布式系统的延迟容错的开源库

 2.Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,提高分布式系统弹性

 3.Hystrix作为“断路器”,当某个服务单元发生故障时,通过断路器的故障监控,向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或抛出调用方无法处理的异常。从而避免雪崩。

1.3、Hystrix作用

 1.服务降级(FallBack):服务器忙时,不让客户端等待并立刻返回一个友好提示。

发生情况:程序运行异常、超时、服务熔断触发服务降级、线程池/信号量也会导致服务降级

 2.服务熔断(Break):达到最大服务访问后,直接拒绝访问,调用服务降级方法并返回友好提示

 3.接近实时的监控(FlowLimit):秒杀高并发等,严禁一窝蜂的过来拥挤,一秒钟N个,有序进行

1.4、Hystrix工作流程

 1、构造一个HystrixCommand或HystrixObservableCommand对象,用于封装请求

 2、执行命令,Hystrix提供了4种执行命令的方法;

 3、判断是否使用缓存响应请求,若启用了缓存,且缓存可用,直接使用缓存响应请求。

 4、判断熔断器是否打开,如果打开,跳到第8步;

 5、判断线程池/队列/信号量是否已满,已满则跳到第8步;

 6、执行HystrixObservableCommand.construct()或HystrixCommand.run(),如果执行失败或者超 时,跳到第8步;否则,跳到第9步;

 7、统计熔断器监控指标;

 8、走Fallback备用逻辑;

 9、返回请求响应。

2、Hystrix案例

2.1、构建正常微服务(服务提供者)

  controller:提供两项,url映射规则

@RestController
@Slf4j
public class PaymentController {
    @Resource
    private PaymentService paymentService;

    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id){
        String result = paymentService.paymentInfo_OK(id);
        log.info("result:" + result);
        return result;
    }

    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
        String result = paymentService.paymentInfo_TimeOut(id);
        log.info("result:" + result);
        return result;
    }
}

2.2、压力测试

2.2.1、Jmeter压测测试

2.2.2、客户端压测测试

 service:调用2.1中提供的微服务接口

@Component
@FeignClient(value = "Provider-hystrix-payment")
public interface OrderHystrixService {
    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id);

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

3、解决方案

3.1、服务降级

  • 设置自身调用超时时间的峰值,峰值内可以正常运行
  • 超过了需要有兜底的方法处理,做服务降级fallback

3.1.1、服务端微服务降级

1.POM文件:添加 hystrix 开发场景

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

2.业务类:@HystrixCommand 声明兜底逻辑

         兜底业务逻辑,针对超时异常,计算异常(int i= 10/0)均可进行兜底

@Service
public class PaymentService {
    //注解中声明paymentInfo_TimeOutHandler方法为兜底业务逻辑,
    //同时声明该业务逻辑的正常执行时长为3秒钟以内
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",
                    commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")})
    public String paymentInfo_TimeOut(Integer id) {
        int timeNumber = 10;
        try{
            TimeUnit.SECONDS.sleep(timeNumber);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "线程池:" + Thread.currentThread().getName() + "paymentInfo_TimeOut,id:" + id + "\t";
    }

    //兜底业务逻辑
    public String paymentInfo_TimeOutHandler(Integer id) {
        return "线程池:" + Thread.currentThread().getName() + "paymentInfo_TimeOutHandler,id:" + id + "\t";
    }
}

3.主启动类:添加 @EnableCircuitBreaker 激活

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class PaymentHystrixMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentHystrixMain8001.class, args);
    }
}

3.1.2、客户端微服务降级

1. POM文件:添加 hystrix 开发场景

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

2. yaml配置文件:开启Hystrix服务降级

#开启hystrix
feign:
  hystrix:
    enabled: true

3.主启动类:添加 @EnableHystrix 激活 Hystrix

@SpringBootApplication
@EnableFeignClients
@EnableHystrix
public class OrderHystrixMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderHystrixMain80.class, args);
    }
}

4.业务类:声明兜底逻辑

@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod", commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})

@RestController
@Slf4j
public class OrderHystrixController {

    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
    })
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
        return orderHystrixService.paymentInfo_TimeOut(id);
    }

    public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {
        return "我是消费者80,对方支付系统繁忙请10秒种后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
    }
}

5.测试结果 

3.1.3、代码优化

1)每个方法都有兜底会引起代码膨胀(业务超时)——客户端微服务代码优化(controller)

        除特殊业务逻辑外,针对普通的业务逻辑,可以设计一个通用的兜底方法,并进行全局配置,防止代码膨胀

   1、@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod") 声明兜底方法

   2、@HystrixCommand 被兜底的方法,利用该注解进行标注

   3、编写全局兜底逻辑payment_Global_FallbackMethod

@RestController
@Slf4j
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class OrderHystrixController {

    @Resource
    private OrderHystrixService orderHystrixService;

    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    @HystrixCommand
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
        return orderHystrixService.paymentInfo_TimeOut(id);
    }

    //下面是全局fallback方法
    public String payment_Global_FallbackMethod() {
        return "Global异常处理信息,请稍后重试.o(╥﹏╥)o";
    }
}

         测试结果:

2)兜底和业务写在一起,代码混乱(服务端宕机或关闭)——客户端微服务解耦(service)

1.新建service类,实现service接口

         service类是对服务端微服务的远程调用时,服务端宕机的兜底逻辑

@Component
public class OrderFallbackService implements OrderHystrixService {
    @Override
    public String paymentInfo_OK(Integer id) {
        return "OrderFallbackService fallback, paymentInfo_OK";
    }

    @Override
    public String paymentInfo_TimeOut(Integer id) {
        return "OrderFallbackService fallback, paymentInfo_TimeOut";
    }
}

2.service 接口,@FeignClient 注解,添加 fallback 属性

        service接口是对服务端接口的远程调用,需要在 @FeignClient 注解中添加 fallback = OrderFallbackService.class ,声明该 service 类是该远程调用接口的兜底逻辑

@Component
@FeignClient(value = "Provider-hystrix-payment", fallback = OrderFallbackService.class)
public interface OrderHystrixService {
    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id);

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

3.配置 yaml 文件,开启Hystrix功能

#开启hystrix
feign:
  hystrix:
    enabled: true

4、测试:依次开启,Eureka服务端、服务端微服务、客户端微服务,并在手动关闭服务端微服务前后,调用客户端url接口,进行服务端远程调用,查看结果。

4、服务熔断

4.1、熔断概念

        熔断机制是应对雪崩效应的一种微服务链路保护机制,当扇出链路的某个微服务出错不可用或者响应时间太长时,会进行服务的降级进而熔断该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后,恢复调用链路。

4.2、熔断实操(服务端微服务)

4.2.1、service层

        1.在被熔断的业务逻辑上添加 @HystrixCommand 注解:

                1)声明熔断后的兜底逻辑

                2)设置熔断参数

        2.添加 paymentCircuitBreaker_fallback 熔断兜底逻辑

@Service
public class PaymentService {
    /** 服务熔断 */
    //表示在时间窗口期中10次请求有6次是错误的,就有调用断路器
    @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback", 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(@PathVariable("id") Integer id) {
        if(id < 0){
            throw new RuntimeException("id,不能为负数");
        }

        String serialNumber = IdUtil.simpleUUID();

        return Thread.currentThread().getName() + "\t" + "调用成功,流水号:" + serialNumber;
    }

    public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) {
        return "id不能为负数,请稍后再试,/(ToT)/~~ id:" + id;
    }
}

 4.2.2、controller层

@RestController
@Slf4j
public class PaymentController {
    @Resource
    private PaymentService paymentService;

    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/payment/circuit/{id}")
    public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
        String result = paymentService.paymentCircuitBreaker(id);
        log.info("result:" + result);
        return result;
    }
}

4.3、 熔断原理

4.3.1、熔断类型

        1)熔断打开:请求不再调用当前服务,内部设置一般为MTTR(平均故障处理时间),

                                当打开时间到达所设时长,则进入半熔断状态。

        2)熔断关闭:熔断关闭后不会对服务进行熔断。

        3)熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则,

                                则认为当前服务恢复正常,关闭熔断。

4.3.2、断路器流程

 1)断路器开启设置:快照时间窗、请求总数阈值、错误百分比阈值

快照时间窗:即统计的时间范围,断路器是否打开需要统计请求和错误数据(默认10s)

请求总数阈值:在快照时间窗内,必须满足请求总数阈值,才有资格熔断(默认20)

错误百分比阈值:请求总数超过阈值时,响应错误占比达到阈值时断路器打开(默认50%)

 2) 断路器运行流程:

  1. 当请求总数及失败率满足一定的阈值的时候,断路器开启
  2. 当开启的时候,所有请求都不会进行转发
  3. 一段时间之后(默认5秒),断路器转为半开状态,会让其中一个请求进行转发.:
    1. 如果成功,断路器会关闭
    2. 若失败,继续开启

 3)断路器打开之后:

        再有请求的时候,将不会调用主逻辑,而是直接调用降级 fallback。通过断路器,实现了自动地发现错误,并将降级逻辑切换为主逻辑,减少响应延迟的效果。

5、服务监控Hystrix Dashboard

5.1、Hystrix Dashboard概述

        Hystrix 提供了准实时的调用监控(Hystrix Dashboard),Hystrix 会持续地记录所有通过 Hystrix 发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括执行多少请求,多少成功、失败等。Spring Cloud也提供了 Hystrix Dashboard 的整合,将监控内容转化成可视化界面。

5.2、Hystrix Dashboard服务搭建

5.2.1、POM文件:

        添加 hystrix-dashboard 开发场景

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

5.2.2、 配置yaml文件(端口号)

server:
  port: 9001

5.2.3、编写主启动类

        添加 @EnableHystrixDashboard 注解,激活 Hystrix Dashboard 组件。

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashBoardMain9001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDashBoardMain9001.class, args);
    }
}

5.2.4、 访问http://localhost:9001/hystrix,得到以下页面

5.3、断路器演示(9001监控8001)

5.3.1、填写监控地址 http://localhost:8001/hystrix.stream

5.3.2、多次调用微服务,并在监控界面打开Monitor stream

 1)查看监控结果:

 2)监控指标说明:

猜你喜欢

转载自blog.csdn.net/weixin_44302046/article/details/124796700
今日推荐