Spring-Cloud:Circuit Breaker


概述

  • 认识circuit breaker
  • 使用circuit breaker
  • 监控
  • 聚合多个 Hystrix streams

认识circuit breaker(断路器)

1.1 简介

  • 在微服务架构中,根据业务拆分成一个个的服务,服务于服务之间可以互相调用(RPC),由于网络或者自身原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被耗尽,导致服务瘫痪,由于服务于服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性后果,这就是服务故障的”雪崩”效应,为了解决这个问题,业界提出了断路器模型(circuit breaker)

  • 当服务出现故障时,可以阻断故障的传播,这就是断路器(circuit breaker)的作用

  • Spring cloud中断路器组件就是Hystrix,它是Netflix套件的一部分。他的功能是,当对某个服务的调用在一定的时间内(默认10s,由metrics.rollingStats.timeInMilliseconds配置),有超过一定次数(默认20次,由circuitBreaker.requestVolumeThreshold参数配置)并且失败率超过一定值(默认50%,由circuitBreaker.errorThresholdPercentage配置),该服务的断路器会打开。返回一个由开发者设定的fallback

使用circuit breaker

2.1 引入Hystrix

  • 可以直接在创建项目时通过Spring Initializr添加

  • pom.xml添加

    //maven依赖
    <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
    //其他需要添加属性
    <properties>
     ...
     <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>
    ...
    <dependencyManagement>
     <dependencies>
     <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-dependencies</artifactId>
     <version>${spring-cloud.version}</version>
     <type>pom</type>
     <scope>import</scope>
     </dependency>
     </dependencies>
    </dependencyManagement>

2.2 启用Hystrix(处理失败)

  • 引入之后,需要在启动类添加@EnableHystrix注解使程序启动时启用Hystrix

    @SpringBootApplication
    @EnableHystrix
    public class IngredientServiceApplication {
     ...
    }
  • 然后在需要断路器处理的方法上使用@HystrixCommand指定该方法出现异常时执行的断路器方法,要求断路器方法返回值和参数与此方法一致

        @HystrixCommand(fallbackMethod = "getDefaultPopInStock")//指定异常时处理的断路器方法
        public PopInStock getById(@PathVariable int id){
            return popInStockRepository.findById(id).get();
        }
  • 增加一个指定的断路器方法(形参和返回值与要处理的方法一致)

        //断路器方法(返回值和形参与其处理的方法一致)
        private PopInStock getDefaultPopInStock(int id){
            return popInStockRepository.findById(1).get();
        }

2.3 处理延迟

  • 如果方法执行延迟超过一定时间(默认为1秒),那么就会触发断路器

        @HystrixCommand(
                fallbackMethod = "getDefaultPopInStock",
                commandProperties = {
                        @HystrixProperty(
                                name="execution.isolation.thread.timeoutInMilliseconds",
                                value="500")//超过500ms就会触发断路器
                }
        )
  • 如果想关闭延迟处理,要一直等待,不会超时,则可以进行如下设置,但是要慎重,这可能导致级联延迟效应

        @HystrixCommand(
                fallbackMethod="getDefaultIngredients",
                commandProperties={
                        @HystrixProperty(
                                name="execution.timeout.enabled",
                                value="false") //关闭超时限制
                })
  • 实例: Controller中指定一个断路器,当方法异常时调用断路器方法(应用需要先启用@EnableHystrix)

    @Controller
    @RequestMapping("/breaker")
    public class CircuitBreakerController {
        @Autowired
        private PopInStockRepository popInStockRepository;
        @GetMapping("/{id}")
        @ResponseBody
        @HystrixCommand(fallbackMethod = "getDefaultPopInStock") //指定断路器
        public PopInStock getById(@PathVariable int id){
            return popInStockRepository.findById(id).get();
        }
        //具体断路器处理方法(形参列表和返回值与处理的方法一致)
        //也可以给断路器方法再指定一个断路器,此断路器异常时执行,不过最终肯定以一个没有断路器的方法结束
        private PopInStock getDefaultPopInStock(int id){ 
            return popInStockRepository.findById(1).get();
        }
    }

2.4 circuit breaker(断路器)阈值设置

  • 默认情况下,如果一个断路器保护方法被调用超过20次,并且超过50%的调用在10秒内失败,那么断路器将会进入open开路状态,所有后续的调用都会直接交给断路器的fallback方法处理,同时在5秒后,此断路器将进入harf-open半开状态,此时将会再次尝试原方法

  • 可以通过设置@HystrixCommand注解中的commandProperties中的@HystrixProperty属性来设置阈值

    属性 描述 默认值
    circuitBreaker.requestVolumeThreshold 给定时间内失败数量达到此数量时触发断路器熔断 20
    circuitBreaker.errorThresholdPercentage 给定时间内方法失败率达到此数量时断路器熔断 50%
    metrics.rollingStats.timeInMilliseconds A rolling time period for which the request volume and error percentage are considered 60000ms
    circuitBreaker.sleepWindowInMilliseconds 熔断多少毫秒后重新尝试原方法 5000ms
  • 注解@HystrixCommand使用实例

        @HystrixCommand(
                fallbackMethod="getDefaultIngredients",
                commandProperties={
                        @HystrixProperty(
                                name="circuitBreaker.requestVolumeThreshold",
                                value="30"),
                        @HystrixProperty(
                                name="circuitBreaker.errorThresholdPercentage",
                                value="25"),
                        @HystrixProperty(
                                name="metrics.rollingStats.timeInMilliseconds",
                                value="20000")
                })
    @HystrixCommand(
     fallbackMethod="getDefaultIngredients",
     commandProperties={
     ...
     @HystrixProperty(
     name="circuitBreaker.sleepWindowInMilliseconds",
     value="60000") //60000ms后重新尝试原方法
     })

监控

3.1 概述

  • *认识: *每次调用断路器保护的方法时都会收集一些关于调用的数据,并发布到HTTP流(Hystrix stream)中,这些数据可以用于实时监控正在运行的应用程序的运行状况,其中收集的数据包含以下内容

    • 方法被调用次数
    • 方法被调用成功次数
    • 断路器fallback方法被调用次数
    • 方法超时次数
  • *依赖: * Hystrix streamActuator endpoint提供,因此需要引入Maven依赖

    <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
  • *配置端点: * 引入Maven依赖之后,Hystrix stream endpoint暴露了一个路径/actuator/hystrix.stream,但是默认情况下禁用的,如果要启用,则需要在application.yml中进行配置,当然可以在Config Server中配置成全局属性,使其他应用都启用

    management:
      endpoints:
        web:
          exposure:
            include: hystrix.stream
  • *Hystrix仪表盘: */actuator/hystrix.stream端点可以通过REST client等去使用,但是因为数据内容很多,自己编写一个对应的客户端并不是很好的选择,可以考虑直接使用Hystrix dashboard(Hystrix仪表盘)

3.2 引入Hystrix dashboard

  • 依赖: 可以在创建项目时通过SpringBoot Initializr引入Hystrix dashboard starter,或者直接在pom.xml引入如下Maven依赖

    <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
  • *启用: * 引入之后需要在应用启动类中添加@EnableHystrixDashboard注解,这样系统启动时才会启用

    @SpringBootApplication
    @EnableHystrixDashboard //启用
    public class HystrixDashboardApplication {
         public static void main(String[] args) {
             SpringApplication.run(HystrixDashboardApplication.class, args);
         }
    }
  • *使用: * 应用启动后,可以通过/hystrix端点查看,如浏览器打开http://localhost:7979/hystrix进入到仪表盘主界面,然后在其中的输入框中输入需要检测的端点actuator/hystrix.stream,如http://localhost:59896/actuator/hystrix.stream,然后查询就会查询出详细的Hystrix stream数据

3.3 Hystrix线程池

  • Hystrix对每个外部依赖用一个单独的线程池(如每个带有@HystrixCommand注解的spring bean),这样的话,如果那个外部依赖调用延迟很严重,最多就是耗尽那个依赖自己的线程池,不会影响其他的依赖调用,最大的好处就是资源隔离
  • Hystrix线程池的缺点是增加了CPU开销,每个Hystrix Command的执行都依托一个独立的线程,会进行排队,调度,还有上下文切换,官方统计结果显示Hystrix的额外开销,就给请求带来了3ms左右的延迟,最多延迟在10ms以内,相对于可用性和稳定性的提升,是可以接受的
  • 作为Hystrix线程池的替代方案,还可以选择semaphore isolation,可以用来限流和削峰,但是不能用来对调研延迟的服务进行timeout和隔离,可以通过设置execution.isolation.strategy = SEMAPHORE开启

聚合多个 Hystrix streams

4.1 概述

  • Hystrix dashboard只能监控一个Hystrix stream,由于每个微服务都会有一个自己的Hystrix stream,对于监控所有微服务是不行的,需要将多个Hystrix stream聚合为单个stream,然后才能监控
  • 对于监控所有微服务可以先通过另一个Netflix project名字为Turbine,它提供了将所有微服务的Hystrix stream聚合为单个stream,然后再使用Hystrix dashboard监控此聚合后的单个stream
  • Turbine可以创建一个单独的微服务作为Eureka ClientEureka Server中获取到其他服务的Hystrix stream(可以通过配置聚合哪些微服务的流)然后聚合为单个stream

4.2 引入Turbine

  • *依赖: *可以通过在创建项目时直接通过SpringBoot Initializr添加,或者在pom.xml中直接引入Maven依赖

    <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
    </dependency>
  • *启用: * 引入依赖之后需要在启动类添加@EnableTurbine注解,才能在启动项目时启用

    @SpringBootApplication
    @EnableTurbine
    public class TurbineServerApplication {
     public static void main(String[] args) {
     SpringApplication.run(TurbineServerApplication.class, args);
     }
    }
  • *配置: * 可以通过在application.yml中配置选择需要聚合哪些微服务的Hystrix stream

    turbine:
     app-config: ingredient-service,taco-service,order-service,user-service #微服务的注册名称
     cluster-name-expression: "'default'" #集群名称
  • Turbine提供了一个端点turbine.stream可以查看聚合后流

4.3 使用

  • 直接在Hystrix dashboard中输入聚合后的Turbine stream(如http://localhost:8989/turbine.stream)就可以查看聚合流的信息

文章作者: Bryson
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Bryson !
评论
 上一篇
下一篇 
Spring-Cloud:Config Spring-Cloud:Config
概述 Config Server 使用共享配置属性 使用应用与特定应用程序的配置属性 保证配置属性安全 动态更新配置属性 Config Server1. 认识1.1 引入bootstrap.yml bootstrap.yml(bootst
2020-08-19
  目录