概述
- 认识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 stream
由Actuator 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 Client
从Eureka 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
)就可以查看聚合流的信息