zoukankan      html  css  js  c++  java
  • 八、Hystrix断路器

    一、概述

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

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

      服务雪崩:多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩”。

      对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和,比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。

      通常当你发现一个模块下的某一个实例失败后,这时候这个模块依然还会接收流量,然后这个有问题的模块还调用了其他模块,这样就会发生级联故障,或者雪崩。

    1.2、Hystrix简介

      Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败避免级联故障,以提高分布式系统的弹性。

      “断路器”本身是一种开关装置,当某个服务单元发生故障后,通过断路器的故障监控,向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要的占用,从而避免了故障在分布式系统中的蔓延、乃至雪崩。

      Hystrix一般用在服务消费端做服务降级。

    1.3、功能作用

    • 服务降级

    • 服务熔断

    • 接近实时的监控

    二、Hystrix重要概念

    2.1、服务降级(fallback)

      “服务器忙,请稍候再试”,不让客户端等待并立刻返回一个友好提示,fallback

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

    2.2、服务熔断break

      类比保险丝达到最大服务访问后,直接==拒绝访问==,拉闸限电,然后调用服务降级的方法并返回友好提示

      服务的降级->进而熔断->恢复调用链路

    2.3、服务限流flowlimit

      秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行

    三、hystrix案例

    3.1、服务提供者

    • 新建Spring Boot 的Module名称:cloud-provider-hystrix-payment8001
    • pom.xml添加如下依赖
    <dependencies>
        <!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    • 编写application.yml
    server:
      port: 8001
    
    
    eureka:
      client:
        register-with-eureka: true    #表识不向注册中心注册自己
        fetch-registry: true   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/
    
    spring:
      application:
        name: cloud-provider-hystrix-payment
    • 主启动类加@EnableEurekaClient注解
    @SpringBootApplication
    @EnableEurekaClient
    public class PaymentHystrixMain8001 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentHystrixMain8001.class,args);
        }
    }
    • 业务类
    @Service
    public class PaymentService {
        //成功
        public String paymentInfo_OK(Integer id) {
            return "线程池:" + Thread.currentThread().getName() + "   paymentInfo_OK,id:  " + id + "	" + "哈哈哈";
        }
    
        //失败
        public String paymentInfo_TimeOut(Integer id) {
            int timeNumber = 3;
            try {
                TimeUnit.SECONDS.sleep(timeNumber);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "线程池:" + Thread.currentThread().getName() + "   paymentInfo_TimeOut,id:  " + id + "	" + "呜呜呜" + " 耗时(秒)" + timeNumber;
        }
    
    }
    @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;
        }
    }
    • 测试

    1、正常测试

    2、高并发测试

      Jmeter压测测试:参考博客

      安装:https://blog.csdn.net/weixin_41077341/article/details/110167555

      使用:https://www.cnblogs.com/stulzq/p/8971531.html

      开启Jmeter,来20000个并发压死cloud-provider-hystrix-payment8001,20000个请求都去访问paymentInfo_TimeOut服务

    3.2、服务消费者

    • 新建Spring Boot Model名称:cloud-consumer-feign-hystrix-order80
    • pom添加如下依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies> 
    • 编写配置文件application.yml
    server
      port: 80
    
    
    eureka:
      client:
        register-with-eureka: true    #表识不向注册中心注册自己
        fetch-registry: true   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
        service-url:
                 defaultZone: http://eureka7001.com:7001/eureka/
    
    spring:
      application:
        name: cloud-provider-hystrix-order 
    • 主启动
    @SpringBootApplication
    @EnableFeignClients
    public class OrderHystrixMain80 {
        public static void main(String[] args) {
          SpringApplication.run(OrderHystrixMain80.class,args);
        }
    }
    • 业务类
    @Component
    @FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")
    public interface PaymentHystrixService {
        @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);
    }
    @RestController
    @Slf4j
    public class OrderHystrixController {
    
        @Resource
        private PaymentHystrixService paymentHystrixService;
    
        @Value("${server.port}")
        private String serverPort;
    
        @GetMapping("/consumer/payment/hystrix/ok/{id}")
        public String paymentInfo_OK(@PathVariable("id") Integer id){
            String result = paymentHystrixService.paymentInfo_OK(id);
            log.info("*******result:"+result);
            return result;
        }
        @GetMapping("/consumer/payment/hystrix/timeout/{id}")
        public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
            String result = paymentHystrixService.paymentInfo_TimeOut(id);
            log.info("*******result:"+result);
            return result;
        }
    
    }
    • 测试

    1、正常测试

      http://localhost/consumer/payment/hystrix/ok/31

    2、高并发测试

      2W个线程压8001;消费端80微服务再去访问正常的OK微服务8001地址;http://localhost/consumer/payment/hystrix/timeout/31

      消费者80;要么转圈圈等待;​ 要么消费端报超时错误

    ​3.3、故障现象和导致原因 

    • 8001同一层次的其他接口服务被困死,因为tomcat线程里面的工作线程已经被挤占完毕

    • 80此时调用8001,客户端访问响应缓慢,转圈圈

    • 正因为有上述故障或不佳表现,才有我们的降级/容错/限流等技术诞生

    3.4、如何解决?解决的要求

      解决思路

      • 超时导致服务器变慢(转圈)------超时不再等待

      • 出错(宕机或程序运行出错)------出错要有兜底

      解决方案

      • 服务提供者(8001)超时了,调用者(80)不能一直卡死等待,必须有服务降级

      • 服务提供者(8001)down机了,调用者(80)不能一直卡死等待,必须有服务降级

      • 服务提供者(8001)OK,调用者(80)自己出故障或有自我要求(自己的等待时间小于服务提供者),自己处理降级

    四、服务降级

      降級配置: @HystrixCommand

    4.1、在服务提供方做降级处理

      8001先从自身找问题;设置自身调用超时时间的峰值,峰值内可以正常运行,超过了需要有兜底的方法处理,作服务降级fallback

    /**
         * fallbackMethod = "paymentInfo_TimeOutHandler"  降级方法
         * @param id
         * @return
         */
        @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")
        })
        public String paymentInfo_TimeOut(Integer id) {
            try { TimeUnit.MILLISECONDS.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
            return "线程池:  "+Thread.currentThread().getName()+" id:  "+id+"	"+"O(∩_∩)O哈哈~"+"  耗时3(秒): ";
        }
    
        /**
         * 服务降级  的兜底方案
         * @param id
         * @return
         */
        public String paymentInfo_TimeOutHandler(Integer id) {
            return "线程池:  "+Thread.currentThread().getName()+" paymentInfo_TimeOutHandler,id:  "+id+"	"+"(●ˇ∀ˇ●)";
        }
    • 业务类启用

      • @HystrixCommand报异常后如何处理

      • 一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法

    • 主启动类激活

      • 添加新注解@EnableCircuitBreaker到主启动类

    4.2、在服务消费方做服务降级

      一般服务降级都是在服务调用方

      80订单微服务,也可以更好的保护自己,微服务客户端降级保护。

    ①、特定fallback

      每一个方法都对应着自己的fallback。

    • application.yml添加如下配置:
    feign:
      hystrix:
        enabled: true #如果处理自身的容错就开启。开启方式与生产端不一样。
    • 主启动添加注解 @EnableHystrix
    • 业务类
    @RestController
    @DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
    public class OrderController { 
        
         @Resource
        private PaymentHystrixService paymentHystrixService;
        
        //调用服务提供方最多等待1.5秒
        @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
                @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
        })
        @GetMapping("/consumer/hystrix/timeout/{id}")
        public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
            String result = paymentHystrixService.paymentInfo_TimeOut(id);
            return result;
        }
    public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) { return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥o"; } }

      目前问题:每个业务方法都对应一个兜底的方法,引起代码膨胀。

    ②、默认fallback

      解决代码膨胀问题:配置默认fallback;每个方法配置一个fallback引起代码膨胀;通过@DefaultProperties(defaultFallback)配置默认fallback

    @RestController
    @DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
    public class OrderController {
        @Resource
        private PaymentHystrixService paymentHystrixService;
    
        //调用服务提供方最多等待1.5秒
        @HystrixCommand
        @GetMapping("/consumer/hystrix/timeout/{id}")
        public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
            String result = paymentHystrixService.paymentInfo_TimeOut(id);
            return result;
        }
        public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {
            return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
        }
    
        // 下面是全局fallback方法
        public String payment_Global_FallbackMethod() {
            return "Global异常处理信息,请稍后再试,/(ㄒoㄒ)/~~";
        }
    }

      目前问题

    • 兜底方法和业务逻辑混一起。我们的业务类PaymentController,目前fallback和业务类混合在一起。这样每一个业务类都需要提供一个兜底方法。

    • 服务降级,客户端去调用服务端,碰上服务端宕机或关闭。本次案例服务降级处理是在客户端80实现完成的,与服务端8001没有关系,只需要为Feign客户端定义的接口添加一个服务降级处理的实现类即可实现解耦。

    ③、全局fallback

      修改cloud-consumer-feign-hystrix-order80。根据cloud-consumer-feign-hystrix-order80已经有的PaymentHystrixService接口,重新新建一个类(PaymentFallbackService)实现该接口,统一为接口里面的方法进行异常处理

    • PaymentFallbackService类实现PaymentFeignClientService接口
    @Component
    public class PaymentFallbackService implements PaymentHystrixService {
        @Override
        public String paymentInfo_OK(Integer id) {
          return "-----PaymentFallbackService fall back-paymentInfo_OK , (┬_┬)";
        }
    
        @Override
      public String paymentInfo_TimeOut(Integer id) {
            return "-----PaymentFallbackService fall back-paymentInfo_TimeOut , (┬_┬)";
      }
    }

      它的运行逻辑是:当请求过来,首先还是通过Feign远程调用pay模块对应的方法。但是如果pay模块报错,调用失败,那么就会调用PayMentFalbackService类的当前同名的方法,作为降级方法。

    • application.yml添加如下配置:
    feign:
      hystrix:
      enabled: true #如果处理自身的容错就开启。开启方式与生产端不一样。
    • PaymentFeignClientService接口
    @Component
    @FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class)
    public interface PaymentHystrixService {
    
        @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);
    }
    • 测试
    • 单个eureka先启动7001;PaymentHystrixMain8001启动

    • 正常访问测试

      • http://localhost/consumer/payment/hystrix/ok/31

      • 故意关闭微服务8001

      • 客户端自己调用提升:此时服务端provider已经down了,但是我们做了服务降级处理,让客户端在服务端不可用时也会获得提示信息而不会挂起耗死服务器

    五、服务熔断

    5.1、熔断机制概述

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

      当检测到该节点微服务调用响应正常后,恢复调用链路。

      在Spring Cloud框架里,熔断机制通过Hystrix实现。Hystrix会监控微服务间调用状况。当失败的调用到一定的阈值,缺省是5秒内20次调用失败,就会启动熔断机制,熔断机制的注解是@HystrixCommand。

    5.2、案例

    @RestController
    @Slf4j
    public class PaymentController {
    
        @Autowired
        private PaymentService paymentService;
    
        //服务熔断
        @GetMapping("/payment/circuit/{id}")
        public String paymentCircuitBreaker(@PathVariable("id") Integer id)
        {
            String result = paymentService.paymentCircuitBreaker(id);
            System.out.println("****result: "+result);
            return result;
        }
    }
    @Service
    public class PaymentService {
    
        /**
         * 传入id >0 正确时打印“调用成功,流水号”
         * 传入id <0 正确时抛出异常
         *
         *10秒中内请求的60%失败,则服务熔断走熔断方法 paymentCircuitBreaker_fallback
         */
        //=====服务熔断     10秒中之内10次访问 失败率超过60% 则触发熔断
        @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()+"	"+"调用成功,流水号: " + serialNumber;
        }
        //熔断后的降级方法
        public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) {
            return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~   id: " +id;
        }
    }

     测试

    • 但是,当过了几秒后,又恢复了。因为在10秒窗口期内,它自己会尝试接收部分请求,发现服务可以正常调用,慢慢的当错误率低于60%,取消熔断

    5.3、服务熔断总结

    1、涉及到断路器的三个重要参数:

    • 快照时间窗:断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认是10秒。

    • 请求总数阈值:在快照时间窗内,必须满足请求总数阈值才有资格熔断。默认是20秒,意味着在10秒内,如果该Hystrix命令的调用次数不超过20次,即使所有的请求都超时或其他原因失败,断路器都不会打开。

    • 错误百分比阈值:当请求总数在快照时间窗口内超过了阈值,比如发生30次调用,如果在这30次调用中,有15次放生了超时异常,也就是超国50%的错误百分比,在默认设定50%阈值情况下,这时候会将断路器打开。

    2、熔断类型:

    • 熔断打开:请求不在进行调用当前服务,内部设置时钟一般为MTR(平均故障时间),当熔断打开时长达到所设时钟则进入半熔断状态。

    • 熔断关闭:熔断关闭不会对服务进行熔断。

    • 熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则,则认为当前服务恢复正常,关闭熔断。

    3、当断路器开启后

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

    2. 原来的主逻辑如何恢复 Hystrix实现了自动恢复功能。当断路器打开,对主逻辑进行熔断后,Hystrix会开启一个休眠时间窗,在这个时间窗内,降级逻辑是临时的成为主逻辑,当休眠的时间窗到期,断路器将进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回,那么断路器将继续闭合,断路器关闭,主逻辑恢复,如果这次请求依然有问题,断路器继续进入打开状态,休眠时间窗重新计时。

    六、hystrix工作流程

    1. 创建HystrixCommand(用在依赖的服务返回单个操作结果的时候)或者HystrixObserableCommand(用在依赖的服务返回多个操作结果的时候)对象。
    2. 命令执行,其中HystrixCommand实现了下面两种执行方式;而HystrixObserableCommand实现后面两种执行方式
      • execute():同步执行,从依赖的服务返回一个单一的结果对象,或是在发生错误的时候抛出异常。

      • queue():异步执行,直接返回一个Future对象,其中包含了服务执行结结束时要返回的单一结果对象。

      • Observe():返回Observable对象,他代表了操作的多个结果,它是一个Hot Obserable(不论“事件源”是否有“订阅者”,都会在创建后对事件进行发布,所以对于Hot Obserable的每一个订阅者都有可能是从“事件源”的中途开始的,并可能只是看到了整个操作的局部过程)

      • toObservable():同样会返回Observable对象,也代表了操作的多个结果,但它返回的是一个Cold Observable(没有定于这的时候并不会发布事件,而是进行等待,直到有订阅者之后才发布事件,所以对于Cold Observable的订阅者,它可以保证从一开始看到整个操作的全部过程)

    3. 若当前命令的请求缓存功能是被启用的,并且该命令缓存命中,那么缓存的结果会立即以Observable对象的形式返回。
    4. 检查断路器是否为打开状态。如果断路器是打开的,那么Hystrix不会执行命令,而是转接到fallback处理逻辑(step 8);如果断路器是关闭的,检查是否有可用资源来执行命令(step 5)
    5. 线程池/请求队列/信号量是否占满,如果命令依赖服务的专有线程池和请求队列,或者信号量(不使用当前线程的时候)已经占满,那么Hystrix也不会执行命令,而是转接到fallback处理逻辑(step 8)
    6. Hystrix会根据我们编写的方法来决定采取什么样的方式去请求依赖服务, Hystrix.run():返回一个单一的结果,或者抛出异常。 HystrixObservableCommand.construct():返回一个Observable对象来发射多个结果,或通过onError发送错误通知。
    7. Hystrix会将“成功”、“失败”、“拒绝”、“超时”等信息报告给断路器,而断路器会维护一组计算器来统计这些数据。断路器会使用这些统计数据来决定是否将断路器打开,来对某个依赖服务的请求进行“熔断/断路”
    8. 当命令执行失败的时候,Hystrix会进入fallabck尝试回退处理,我们通常也称该操作为“服务降级”。而能够引起服务降级处理的情况有下面几种 step4:当前命令处于“熔断/断路”状态,断路器是打开的时候。 step5:当前命令是线程池、请求队列或者信号量被占满的时候。 step6:Hystrix.run()或者HystrixObservableCommand.construct()抛出异常的时候。
    9. 当Hystrix命令执行成功之后,他会将处理结果直接返回或是以Observable形式返回。

      注意:我们没有为命令实现降级逻辑或者在降级处理逻辑中抛出异常,Hystrix依然会返回一个Observable对象,但是他不会发射任何结果数据,而是通过onError方法通知命令立即中断请求,并通过onError()方法将引起命令失败的异常发送给调用者。

    七、服务监控hystrixDashboard

    7.1、概述

      除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求,多少成功,多少失败等,Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控,Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。

    7.2、案例

    • 新建Spring Boot Model名称:cloud-consumer-hystrix-dashboard9001
    • pom添加如下依赖
    <dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    • 编写applicatin.yml
    server:
      port: 9001
    • HystrixDashboardMain9001+新注解@EnableHystrixDashboard
    @SpringBootApplication
    @EnableHystrixDashboard
    public class HystrixDashboardMain9001 {
        public static void main(String[] args) {
            SpringApplication.run(HystrixDashboardMain9001.class,args);
        }
    }
    • 启动cloud-consumer-hystrix-dashboard9001该微服务后续将监控微服务8001; http://localhost:9001/hystrix

    7.3、断路器演示

      修改cloud-provider-hystrix-payment8001;注意:新版本Hystrix需要在主启动类MainAppHystrix8001中指定监控路径。否则报Unable to connect to Command Metric Stream、404

    @Bean
    public ServletRegistrationBean getServlet(){
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

      监控测试

      • 启动1个eureka或者3个eureka集群均可
      • 观察监控窗口:9001监控8001;http://localhost:8001/hystrix.stream

      测试地址:http://localhost:8001/payment/circuit/31;http://localhost:8001/payment/circuit/-31

      上述测试通过先访问正确地址,再访问错误地址,再正确地址,会发现图示断路器都是慢慢放开的。

  • 相关阅读:
    (转)ELK Stack 中文指南--性能优化
    (转)如何在CentOS / RHEL 7上安装Elasticsearch,Logstash和Kibana(ELK)
    (转)GlusterFS 01 理论基础,企业实战,故障处理
    (转)CentOS7.4环境下搭建--Gluster分布式集群存储
    (转)DB2性能优化 – 如何通过调整锁参数优化锁升级
    (转)架构师之DNS实战CentOS7VSCentOS6
    PHP:计算文件或数组中单词出现频率
    [获取行数]php读取大文件提供性能的方法,PHP的stream_get_line函数读取大文件获取文件的行数的方...
    Windows下配置环境变量和需不需要重启问题
    CENTOS 下安装APK反编译工具 APKTOOL
  • 原文地址:https://www.cnblogs.com/jdy1022/p/14555409.html
Copyright © 2011-2022 走看看