Hystrix原理及其使用

  • Post author:
  • Post category:其他



目录


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)监控指标说明:



版权声明:本文为weixin_44302046原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。