zoukankan      html  css  js  c++  java
  • SpringCloud学习之Hystrix

    一、为什么要有断路器

      在分布式系统当中,服务之间调用关系会随着业务的发展而变的复杂,一个服务可能依赖多个服务,服务之间层层依赖也是家常便饭的事情,如果一个服务的瘫痪很有可能导致整个系统的崩溃。比如说,现在每栋房子,每家每户都有电闸,电闸的作用是保证有一家用电出现异常时,电闸进行断电跳闸的操作,这样不至于导致整栋楼用电瘫痪,那么我们的系统也是如此:我们请看下图:

      

      

    这个系统架构中由于服务I的异常(可能是程序运行错误,可能是系统阻塞,可能是负载过重等等),渐渐的导致整个系统崩溃,我们称之为雪崩效应

    二、关于Hystrix

    1. Hystrix对应的中文名字是“豪猪”,豪猪周身长满了刺,能保护自己不受天敌的伤害,代表了一种防御机制,Hystrix提供了熔断、隔离、Fallback、cache、监控等功能,能够在一个、或多个依赖同时出现问题时保证系统依然可用。
    2. Hystrix通过四个方面的机制来解决这个问题
      • 隔离(线程池隔离和信号量隔离):限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其他服务调用。线程隔离:每个服务都为一个个独立的线程组,当I服务出现问题时,不会导致整个服务瘫痪。由于线程隔离会带来线程开销,有些场景(比如无网络请求场景)可能会因为用开销换隔离得不偿失,为此hystrix提供了信号量隔离,当服务的并发数大于信号量阈值时将进入fallback。

          隔离策略示例图

          

      • 优雅的降级机制:超时降级、资源不足时(线程或信号量)降级,降级总之是一种退而求其次的方式,根据业务场景的不同,一般采用以下两种模式进行降级:第一种(最常用)如果服务失败,则我们通过fallback进行降级,返回静态值。第二种:调用备选方案
      • 融断:当失败率达到阀值自动触发降级(如因网络故障/超时造成的失败率高),熔断器触发的快速失败会进行快速恢复。类似于电闸

          

      • 缓存:提供了请求缓存、请求合并实现。
      • 支持实时监控、报警、控制(修改配置)

    三、Hystrix使用方法

      3.1)继承HystrixCommand类,重写run方法与getFallBack方法,简单的代码示例:

    package com.bdqn.lyrk.springcloud.order.hystrix;
    
    import com.netflix.hystrix.HystrixCommand;
    import com.netflix.hystrix.HystrixCommandGroupKey;
    
    public class HelloWorldHystrix extends HystrixCommand<String> {
    
        public HelloWorldHystrix() {
            super(HystrixCommandGroupKey.Factory.asKey("first"));
        }
    
        @Override
        protected String run() throws Exception {
            //Thread.sleep(10000);
            System.out.println("running...");
           // System.out.println(1 / 0);
            return "running...";
        }
    
        @Override
        protected String getFallback() {
            System.out.println("error running...");
            return "error running...";
        }
    }
    View Code

      3.2)  设置信号量隔离策略,初次接触设置属性的代码比较复杂,更多的可以参考wiki

    public HelloWorldHystrix() {
            super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("first"))
                            .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                            .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE))
                            .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withQueueSizeRejectionThreshold(10))
                            .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionIsolationSemaphoreMaxConcurrentRequests(10))
                            .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withFallbackIsolationSemaphoreMaxConcurrentRequests(50))
            );
        }
    View Code

      3.3)针对于3.2,我们可以创建如下线程进行调用:

     

    for (int i = 0; i < 50; i++) {
                new Thread(() -> {
                    HelloWorldHystrix helloWorldHystrix = new HelloWorldHystrix();
                    helloWorldHystrix.execute();
                }).start();
    
            }
    View Code

     四。spring-cloud中使用Hystrix

      4.1) 添加相关依赖

      

    compile('org.springframework.cloud:spring-cloud-starter-hystrix')
    compile('org.springframework.cloud:spring-cloud-starter-hystrix-dashboard')

      4.2) 在启动类上添加 @EnableCircuitBreaker与@EnableHystrixDashboard注解

      

    package com.bdqn.lyrk.springcloud.order;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
    
    @SpringBootApplication
    @EnableEurekaServer
    @EnableCircuitBreaker
    @EnableHystrixDashboard
    public class OrderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    }
    View Code

      4.3)添加@HystrixCommand注解

      

    package com.bdqn.lyrk.springcloud.order.controller;
    
    import com.bdqn.lyrk.service.api.IOrderService;
    import com.bdqn.lyrk.service.dto.OrderDTO;
    import com.bdqn.lyrk.springcloud.order.config.StudentConfig;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.context.config.annotation.RefreshScope;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.concurrent.TimeUnit;
    
    @RestController
    @RefreshScope
    public class OrderController {
    
        @Autowired
        private StudentConfig studentConfig;
    
        @Autowired
        private IOrderService orderService;
    
        @GetMapping("/getInfo")
        public String getInfo() {
            return studentConfig.getName() + ":" + studentConfig.getAge();
        }
    
        @GetMapping("/orderId/{orderId}")
        @HystrixCommand(fallbackMethod = "getFailedOrder", commandProperties = {
                @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
                , @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2")
        })
        public OrderDTO getOrderById(@PathVariable("orderId") Integer orderId) throws InterruptedException {
            TimeUnit.SECONDS.sleep(orderId);
            return orderService.getOrderById(orderId);
        }
    
        public OrderDTO getFailedOrder(Integer orderId) {
            OrderDTO orderDTO = new OrderDTO();
            orderDTO.setOrderName("失败的订单");
            return orderDTO;
        }
    }
    View Code

      注意其中有两个关键属性分别为:

       execution.isolation.thread.timeoutInMilliseconds 这个是请求最大的响应时间

       circuitBreaker.requestVolumeThreshold 如果执行失败的次数等于或者超过这个值就开启保护

      4.4)当我们的系统添加actutator时,我们可以访问请求地址:http://localhost:8001/health 来检测状态

      此时我们通过http://localhost:8001/orderId/4访问三次服务得到如下结果

      注意,此时断路器打开保护机制

      4.5)使用Hystrix的仪表盘

        还记得我们添加 spring-cloud-starter-netflix-hystrix-dashboard的依赖么?通过访问http://localhost:8001/hystrix就可以得到如下界面

      

  • 相关阅读:
    猫 先吃药
    用抛物线筛选素数
    999999999分解质因数
    九宫数独简介(转)
    空间想象力大战!Smale球面外翻问题
    神奇的分形艺术(一):无限长的曲线可能围住一块有限的面积
    Kobon问题新进展:17条直线可构成多少个互不重叠的三角形
    关于2008:你必须知道的10个事实
    正多边形的滚动与旋轮线下的面积
    我见过的最酷的排序算法演示(乐死我了~)
  • 原文地址:https://www.cnblogs.com/niechen/p/8513597.html
Copyright © 2011-2022 走看看