一、高可用系统架构:
- 资源隔离:让你的系统里,某一块东西,在故障的情况下,不会耗尽系统所有的资源,比如线程资源。
- 限流:高并发的流量涌入进来,比如说突然间一秒钟100万QPS,废掉了,10万QPS进入系统,其他90万QPS被拒绝了。
- 熔断:系统后端的一些依赖,出了一些故障,比如说mysql挂掉了,每次请求都是报错的,熔断了,后续的请求过来直接不接收了,拒绝访问,10分钟之后再尝试去看看mysql恢复没有
- 降级:mysql挂了,系统发现了,自动降级,从内存里存的少量数据中,去提取一些数据出来
- 运维监控:监控+报警+优化,各种异常的情况,有问题就及时报警,优化一些系统的配置和参数,或者代码。
二、雪崩效应
分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务。
比如我们现在有3个业务调用分别是查询订单
、查询商品
、查询用户
,且这三个业务请求都是依赖第三方服务-订单服务
、商品服务
、用户服务
。三个服务均是通过RPC调用。当查询订单服务
,假如线程阻塞了,这个时候后续有大量的查询订单
请求过来,那么容器中的线程数量则会持续增加直致CPU资源耗尽到100%,整个服务对外不可用,并且这种可不用可能沿请求调用链向上传递,这种现象在集群环境下就是雪崩。如下图
复杂分布式体系结构中的应用程序有几十个依赖项,每个依赖项在某个时候都不可避免地会失败。如果主机应用程序没有从这些外部故障中隔离出来,那么它就有可能与这些外部故障一起宕机。
-
当一切正常时,请求流可以是这样的:
- 当许多后端系统之一成为潜在,它可以阻止整个用户请求:
-
在高并发下,一个后端依赖项出现问题,可能会导致所有服务器上的所有资源在几秒钟内饱和。应用程序中通过网络或客户机库到达可能导致网络请求的每个点都是潜在故障的来源。比故障更糟的是,这些应用程序还可能导致服务之间的延迟增加,从而备份队列、线程和其他系统资源,从而导致系统中出现更多级联故障。
一个应用中,任意一个点的不可用或者响应延时都有可能造成服务不可用
更可怕的是,被hang住的请求会很快耗尽系统的资源,当该类请求越来越多,占用的计算机资源越来越多的时候,会导致系统瓶颈出现,造成其他的请求同样不可用,最终导致业务系统崩溃
雪崩效应常见场景
- 硬件故障:如服务器宕机,机房断电,光纤被挖断等。
- 流量激增:如异常流量,重试加大流量等。
- 缓存穿透:一般发生在应用重启,所有缓存失效时,以及短时间内大量缓存失效时。大量的缓存不命中,使请求直击后端服务,造成服务提供者超负荷运行,引起服务不可用。
- 程序BUG:如程序逻辑导致内存泄漏,JVM长时间FullGC等。
- 同步等待:服务间采用同步调用模式,同步等待造成的资源耗尽。
最终的结果就是一个服务不可用导致一系列服务的不可用,而往往这种后果往往无法预料的。
雪崩效应应对策略
- 硬件故障:多机房容灾、异地多活等。
- 流量激增:服务自动扩容、流量控制(限流、关闭重试)等。
- 缓存穿透:缓存预加载、缓存异步加载等。
- 程序BUG:修改程序bug、及时释放资源等。
- 同步等待:资源隔离、MQ解耦、不可用服务调用快速失败等。资源隔离通常指不同服务调用采用不同的线程池;不可用服务调用快速失败一般通过超时机制,熔断器以及熔断后降级方法等方案实现。
三、Hystrix的产生
1. Hystrix的设计目标
- 对来自依赖的延迟和故障进行防护和控制——这些依赖通常都是通过网络访问的
- 阻止故障的连锁反应
- 快速失败并迅速恢复
- 回退并优雅降级
- 提供近实时的监控与告警
2. Hystrix遵循的设计原则
- 防止任何单独的依赖耗尽资源(线程)
- 过载立即切断并快速失败,防止排队
- 尽可能提供回退以保护用户免受故障
- 使用隔离技术(例如隔板,泳道和断路器模式)来限制任何一个依赖的影响
- 通过近实时的指标,监控和告警,确保故障被及时发现
- 通过动态修改配置属性,确保故障及时恢复
- 防止整个依赖客户端执行失败,而不仅仅是网络通信
3. Hystrix如何实现这些设计目标?
- 使用命令模式将所有对外部服务(或依赖关系)的调用包装在HystrixCommand或HystrixObservableCommand对象中,并将该对象放在单独的线程中执行;
- 每个依赖都维护着一个线程池(或信号量),线程池被耗尽则拒绝请求(而不是让请求排队)。
-
记录请求成功,失败,超时和线程拒绝。
服务错误百分比超过了阈值,熔断器开关自动打开,一段时间内停止对该服务的所有请求。
请求失败,被拒绝,超时或熔断时执行降级逻辑。
近实时地监控指标和配置的修改。
三、hystrix实现原理
Hystrix实现了熔断机制、请求超时、限流降级、结果缓存、请求合并、统计、线程池隔离等功能共同保障应用的稳定性。
流程说明:
1:每次调用创建一个新的HystrixCommand,把依赖调用封装在run()方法中.
2:执行execute()/queue做同步或异步调用.
3:判断熔断器(circuit-breaker)是否打开,如果打开跳到步骤8,进行降级策略,如果关闭进入步骤.
4:判断线程池/队列/信号量是否跑满,如果跑满进入降级步骤8,否则继续后续步骤.
5:调用HystrixCommand的run方法.运行依赖逻辑
5a:依赖逻辑调用超时,进入步骤8.
6:判断逻辑是否调用成功
6a:返回成功调用结果
6b:调用出错,进入步骤8.
7:计算熔断器状态,所有的运行状态(成功, 失败, 拒绝,超时)上报给熔断器,用于统计从而判断熔断器状态.
8:getFallback()降级逻辑.
以下四种情况将触发getFallback调用:
(1):run()方法抛出非HystrixBadRequestException异常。
(2):run()方法调用超时
(3):熔断器开启拦截调用
(4):线程池/队列/信号量是否跑满
8a:没有实现getFallback的Command将直接抛出异常
8b:fallback降级逻辑调用成功直接返回
8c:降级逻辑调用失败抛出异常
9:返回执行成功结果
1. 隔离
(1)线程池隔离模式:使用一个线程池来存储当前的请求,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求堆积入线程池队列。这种方式需要为每个依赖的服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理)
(2)信号量隔离模式:使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,请求来先判断计数器的数值,若超过设置的最大线程个数则丢弃改类型的新请求,若不超过则执行计数操作请求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服务)
区别(两种隔离方式只能选其一):
对比角度 | 线程池隔离 | 信号量隔离 |
---|---|---|
线程 | 与调用线程非相同线程 | 与调用线程相同(jetty线程) |
开销 | 排队、调度、上下文开销等 | 无线程切换,开销低 |
异步 | 支持 | 不支持 |
并发支持 | 支持(最大线程池大小) | 支持(最大信号量上限) |
线程池和信号量都支持熔断和限流。相比线程池,信号量不需要线程切换,因此避免了不必要的开销。但是信号量不支持异步,也不支持超时,也就是说当所请求的服务不可用时,信号量会控制超过限制的请求立即返回,但是已经持有信号量的线程只能等待服务响应或从超时中返回,即可能出现长时间等待。线程池模式下,当超过指定时间未响应的服务,Hystrix会通过响应中断的方式通知线程立即结束并返回。
2. 融断
正常状态下,电路处于关闭状态(Closed),如果调用持续出错或者超时,电路被打开进入熔断状态(Open),后续一段时间内的所有调用都会被拒绝(Fail Fast),一段时间以后,保护器会尝试进入半熔断状态(Half-Open),允许少量请求进来尝试,如果调用仍然失败,则回到熔断状态,如果调用成功,则回到电路闭合状态;
3. 降级
可能大家会混淆“融断”和“降级”两个概念。
在股票市场,熔断这个词大家都不陌生,是指当股指波幅达到某个点后,交易所为控制风险采取的暂停交易措施。相应的,服务熔断一般是指软件系统中,由于某些原因使得服务出现了过载现象,为防止造成整个系统故障,从而采用的一种保护措施,所以很多地方把熔断亦称为过载保护。
大家都见过女生旅行吧,大号的旅行箱是必备物,平常走走近处绰绰有余,但一旦出个远门,再大的箱子都白搭了,怎么办呢?常见的情景就是把物品拿出来分分堆,比了又比,最后一些非必需品的就忍痛放下了,等到下次箱子够用了,再带上用一用。而服务降级,就是这么回事,整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开启回来。
二者的目标是一致的,目的都是保证上游服务的稳定性。但其关注的重点并不一样,融断对下层依赖的服务并不级(或者说孰轻孰重),一旦产生故障就断掉;而降级需要对下层依赖的业务分级,把产生故障的丢了,换一个轻量级的方案,是一种退而求其次的方法。
根据业务场景的不同,一般采用以下两种模式:
第一种(最常用)如果服务失败,则我们通过fallback进行降级,返回静态值。
第二种采用服务级联的模式,如果第一个服务失败,则调用备用服务,例如失败重试或者访问缓存失败再去取数据库。服务级联的目的则是尽最大努力保证返回数据的成功性,但如果考虑不充分,则有可能导致级联的服务崩溃(比如,缓存失败了,把全部流量打到数据库,瞬间导致数据库挂掉)。因此级联模式,也要慎用,增加了管理的难度。
4. 缓存
不建议使用,对问题排查会造成很大的困扰
四、使用Hystrix
1. 添加maven依赖:
<!--添加Hystrix依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
2. 修改启动类
在主函数上添加注解@EnableCircuitBreaker
,启动Hystrix
Circuit
n. 环行; 环行路线; 电路; 线路; 巡回赛;
@SpringBootApplication
@EnableEurekaClient//声明为eureka 客户端
@EnableFeignClients //启动Feign
@EnableCircuitBreaker //启动Hystrix
public class FuturecloudHystrixApplication
{
public static void main( String[] args )
{
SpringApplication.run(FuturecloudHystrixApplication.class,args);
}
}
3. Feign 接口
(可以不使用)
@FeignClient(name = "futurecloud-user") //通过注解指定依赖服务
public interface FeignClientInterfaces {
@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
User getUserById(@PathVariable("id") Long id);
@GetMapping("/getUser/{id}")
User getUser(@PathVariable("id") Long id);
@RequestMapping(value = "/find/user/{id}",method = RequestMethod.POST)
User findUserById(@PathVariable("id") Long id);
}
4、使用Hystix熔断器
@RestController
public class FuturecloudHystrixController {
@Autowired
private FeignClientInterfaces feignClientInterfaces;
@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
public User getUserById(@PathVariable("id") Long id){
User user = feignClientInterfaces.getUserById(id);
return user;
}
@GetMapping("/getUser/{id}")
public User getUser(@PathVariable("id") Long id){
User user = feignClientInterfaces.getUser(id);
return user;
}
/**
* 使用Hystrix熔断器,当调用findUserById失败后,调用forbackFindUserById方法
* @param id
* @return
*/
@HystrixCommand(fallbackMethod = "forbackFindUserById")
@RequestMapping(value = "/find/user/{id}",method = RequestMethod.GET)
public User findUserById(@PathVariable("id") Long id){
User user = feignClientInterfaces.findUserById(id);
int a = 4/0;
return user;
}
public User forbackFindUserById(Long id){
User user = new User();
user.setId(-400L);
user.setUsername("hystrix-fallback");
user.setMail("hystrix-fallback@sina.com");
user.setPhone("13838384381");
user.setCreateDate(new Date());
return user;
}
}
使用这个注解@HystrixCommand来定义Hystrix的熔断器,查看HystrixCommand源码,这个注解有10个属性,
我们使用fallbackMethod属性,来指定接口调用失败后执行的方法。
*********************************************************************************************************************************************************************** | 说明 |
---|---|
commandKey | 配置全局唯一标识服务的名称,比如,库存系统有一个获取库存服务,那么就可以为这个服务起一个名字来唯一识别该服务,如果不配置,则默认是@HystrixCommand注解修饰的函数的函数名。 |
groupKey | 一个比较重要的注解,配置全局唯一标识服务分组的名称,比如,库存系统就是一个服务分组。通过设置分组,Hystrix会根据组来组织和统计命令的告、仪表盘等信息。Hystrix命令默认的线程划分也是根据命令组来实现。默认情况下,Hystrix会让相同组名的命令使用同一个线程池,所以我们需要在创建Hystrix命令时为其指定命令组来实现默认的线程池划分。此外,Hystrix还提供了通过设置threadPoolKey来对线程池进行设置。建议最好设置该参数,使用threadPoolKey来控制线程池组。 |
threadPoolKey | 对线程池进行设定,细粒度的配置,相当于对单个服务的线程池信息进行设置,也可多个服务设置同一个threadPoolKey构成线程组。 |
fallbackMethod | @HystrixCommand注解修饰的函数的回调函数,@HystrixCommand修饰的函数必须和这个回调函数定义在同一个类中,因为定义在了同一个类中,所以fackback method可以是public/private均可。 |
commandProperties | 配置该命令的一些参数,如executionIsolationStrategy配置执行隔离策略,默认是使用线程隔离,此处我们配置为THREAD,即线程池隔离。参见:com.netflix.hystrix.HystrixCommandProperties中各个参数的定义。 |
threadPoolProperties | 线程池相关参数设置,具体可以设置哪些参数请见:com.netflix.hystrix.HystrixThreadPoolProperties |
ignoreExceptions | 调用服务时,除了HystrixBadRequestException之外,其他@HystrixCommand修饰的函数抛出的异常均会被Hystrix认为命令执行失败而触发服务降级的处理逻辑(调用fallbackMethod指定的回调函数),所以当需要在命令执行中抛出不触发降级的异常时来使用它,通过这个参数指定,哪些异常抛出时不触发降级(不去调用fallbackMethod),而是将异常向上抛出。 |
observableExecutionMode | 定义hystrix observable command的模式; |
raiseHystrixExceptions | 任何不可忽略的异常都包含在HystrixRuntimeException中; |
defaultFallback | 默认的回调函数,该函数的函数体不能有入参,返回值类型与@HystrixCommand修饰的函数体的返回值一致。如果指定了fallbackMethod,则fallbackMethod优先级更高。 |
5. application.yml
server:
port: 8906
spring:
application:
name: futurecloud-hystrix
#将此服务注册到eureka 服务上
eureka:
client:
serviceUrl:
defaultZone: http://user:123@localhost:10000/eureka
instance:
prefer-ip-address: true #将注册到eureka服务的实例使用ip地址
#Feign日志的配置
logging:
level:
com.futurecloud.feign.interfaces.CustomFeignClient: DEBUG
启动eureka 服务futurecloud-service,
启动服务提供者服务futurecloud-user,
启动此服务futurecloud-hystrix
访问http://localhost:8906/order/20 ,进入到了@HystrixCommand指定的方法forbackFindUserById
五、Feign 使用Hystrix
在Feign 接口中定义了依赖服务的接口,当Feign调用依赖服务的接口失败时怎么办?
我们也可以在Feign中利用Hystrix的功能,当Feign 调用依赖服务的接口失败时,通过Hystrix调用指定的方法,Spring Cloud默认为Feign整合了Hystrix,但在Spring Cloud 基于Spring boot 2.x的版本中,默认是Feign是关闭Hystrix的。
那么Feign与Hystrix怎么配合使用呢?
1、创建项目futurecloud-feign-hystrix
注意:不需要添加依赖spring-cloud-starter-netflix-hystrix,Spring Cloud默认已为Feign整合了Hystrix。spring boot 主函数也不需要添加注解@EnableCircuitBreaker 来开启Hystrix。主函数类如下:
@SpringBootApplication
@EnableEurekaClient //声明为eureka 客户端
@EnableFeignClients //启动Feign
public class FuturecloudFeignHystrixApplication
{
public static void main( String[] args )
{
SpringApplication.run(FuturecloudFeignHystrixApplication.class,args);
}
}
2. 开启Hystrix在application.yml中配置
#开启hystrix配置
feign:
hystrix:
enabled: true
2、Feign 使用fallback 方式进行Hystrix的回退
在定义Feign接口时,我们可以指定Feign接口中的方法调用失败后的一个回调类,这个类实现此Feign接口,
Feign接口代码如下:
@FeignClient(name = "futurecloud-user",fallback = FeignHystrixFallback.class) //指定依赖服务Hystrixd的回调类
public interface FeignInterface {
@GetMapping("/user/{id}")
User getUser(@PathVariable("id") Long id);
@GetMapping("/getObject")
User getObject(User user);
@GetMapping("/find//user/{id}")
User findUser(@PathVariable("id") Long id);
}
FeignHystrixFallback 代码如下:
@Component
public class FeignHystrixFallback implements FeignInterface{
@Override
public User getUser(Long id) {
User user = new User();
user.setId(-401L);
user.setUsername("01-feignHystrixFallback");
user.setMail("hystrix-fallback@sina.com");
user.setPhone("13838389438");
user.setCreateDate(new Date());
return user;
}
@Override
public User getObject(User user) {
user = new User();
user.setId(-402L);
user.setUsername("02-feignHystrixFallback");
user.setMail("hystrix-fallback@sina.com");
user.setPhone("13838389438");
user.setCreateDate(new Date());
return user;
}
@Override
public User findUser(Long id) {
User user = new User();
user.setId(-403L);
user.setUsername("03-feignHystrixFallback");
user.setMail("hystrix-fallback@sina.com");
user.setPhone("13838389438");
user.setCreateDate(new Date());
return user;
}
}
注意:要添加注解@Component,否则Spring boot 找不到这个bean
启动eureka 服务futurecloud-service,
启动服务提供者服务futurecloud-user,
启动此服务futurecloud-feign-hystrix
访问http://localhost:8907/order/20 ,成功访问
将服务futurecloud-user关掉,再一次访问http://localhost:8907/order/20,调用了fallback指定的FeignHystrixFallback中的方法。
3. Feign 使用fallbackFactory方式进行Hystrix的回退
在Feign接口中指定使用fallbackFactory工厂类,其实就是实现Feign接口的匿名类
Feign接口定义如下:
@FeignClient(name = "futurecloud-user",fallbackFactory = FeignHystrixFallbackFactory.class)
public interface FeignInterface {
@GetMapping("/user/{id}")
User getUser(@PathVariable("id") Long id);
@GetMapping("/getObject")
User getObject(User user);
@GetMapping("/find//user/{id}")
User findUser(@PathVariable("id") Long id);
}
FeignHystrixFallbackFactory代码如下:
@Component
public class FeignHystrixFallbackFactory implements FallbackFactory<FeignInterface>{
@Override
public FeignInterface create(Throwable throwable) {
return new FeignInterface() {
@Override
public User getUser(Long id) {
User user = new User();
user.setId(-404L);
user.setUsername("01-feignHystrixFallbackFactory");
user.setMail("hystrix-fallback@sina.com");
user.setPhone("13838389438");
user.setCreateDate(new Date());
return user;
}
@Override
public User getObject(User user) {
user = new User();
user.setId(-405L);
user.setUsername("02-feignHystrixFallbackFactory");
user.setMail("hystrix-fallback@sina.com");
user.setPhone("13838389438");
user.setCreateDate(new Date());
return user;
}
@Override
public User findUser(Long id) {
User user = new User();
user.setId(-406L);
user.setUsername("03-feignHystrixFallbackFactory");
user.setMail("hystrix-fallback@sina.com");
user.setPhone("13838389438");
user.setCreateDate(new Date());
return user;
}
};
}
}
其余配置与fallback一致。
启动eureka 服务futurecloud-service,
启动服务提供者服务futurecloud-user,
启动此服务futurecloud-feign-hystrix
访问http://localhost:8907/order/20 ,成功访问
将服务futurecloud-user关掉,再一次访问http://localhost:8907/order/20,调用了fallbackFactory指定的FeignHystrixFallbackFactory中的方法。
六、Hystrix的健康监测
1. actuator
①添加依赖
<!--添加认证监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
②浏览器访问 http://192.168.215.2:8908/actuator/health
就能显示Hystrix开启状态信息。
有人说,Spring boot 2.x 使用了endpoint,导致/actuator/health,/actuator/hystrix.stream都无法访问,报404错误。
我用的Spring Cloud 版本是Finchley.RELEASE,但是我没遇上,如果有人遇上,可以试试以下三种方法。而我将以下三种方法注释掉,一样能显示Hystrix的/actuator/health,/actuator/hystrix.stream信息
设置让endpoint允许显示/actuator/health,/actuator/hystrix.stream信息的方法如下:
方式一:在application.yml中添加如下配置:
management:
endpoint:
health:
show-details: always #允许显示/actuator/health信息
management:
endpoints:
web:
exposure:
include: ["hystrix-stream"] #允许显示/actuator/hystrix.stream信息
management:
endpoints:
web:
exposure:
include: '*' #允许显示所有信息,包括/actuator/health,/actuator/hystrix.stream
解决方式二:在Hystrix监控项目的启动类中添加方法,设置允许显示的信息
/**
* 配置Hystrix ,使其显示健康监测信息
* @return
*/
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/actuator/health","/actuator/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
解决方式三:在application.yml中打开Feign 的Hystrix
*************************************************************
#开启hystrix配置
feign:
hystrix:
enabled: true
2. Hystrix-DashBoard的使用
即前面说的/hystrix.stream 详细信息的图形化。
①引入依赖
<!--添加hystrix dashboard依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
②在主函数上添加配置@EnableHystrixDashboard,开启Hystrix-DashBoard
@SpringBootApplication
@EnableHystrixDashboard //开启Hystrix-DashBoard
public class FuturecloudHystrixDashBoardApplication
{
public static void main( String[] args )
{
SpringApplication.run(FuturecloudHystrixDashBoardApplication.class,args);
}
}
③配置文件增加endpoint
management:
endpoints:
web:
exposure:
include: "*"
④访问入口
http://localhost:8781/hystrix
Hystrix Dashboard输入: http://localhost:8781/actuator/hystrix.stream
七. 补充
一、hystrix参数使用方法
@RestController
public class MovieController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/movie/{id}")
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
@HystrixProperty(name = "execution.timeout.enabled", value = "false")},fallbackMethod = "findByIdFallback")
public User findById(@PathVariable Long id) {
return this.restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class);
}
/**
* fallback方法
* @param id
* @return
*/
public User findByIdFallback(Long id) {
User user = new User();
user.setId(5L);
return user;
}
}
或者 application.yml
feign:
hystrix:
enabled: true //feign开启hystrix支持【这里开启了,启动类就不用了】
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 500 //线程超时,调用Fallback方法
circuitBreaker:
requestVolumeThreshold: 3 //10秒内出现3个以上请求(已临近阀值),并且出错率在50%以上,开启断路器.断开服务,调用Fallback方法
二、hystrix参数如下
**********参数类型********** | 参数名 | 默认值 | 说明 |
---|---|---|---|
command配置 | executionIsolationStrategy | ExecutionIsolationStrategy.THREAD | 信号隔离或线程隔离,默认:采用线程隔离, |
executionIsolationThreadTimeoutInMillisecond | 1s | 隔离时间大,即多长时间后进行重试 | |
executionIsolationSemaphoreMaxConcurrentRequests | 10 | 使用信号量隔离时,命令调用最大的并发数,默认:10 | |
fallbackIsolationSemaphoreMaxConcurrentRequests | 10 | 使用信号量隔离时,命令fallback(降级)调用最大的并发数,默认:10 | |
fallbackEnabled | true | 是否开启fallback降级策略 | |
executionIsolationThreadInterruptOnTimeout | true | 使用线程隔离时,是否对命令执行超时的线程调用中断(Thread.interrupt())操作 | |
metricsRollingStatisticalWindowInMilliseconds | 10000ms | 统计滚动的时间窗口,默认:10s | |
metricsRollingStatisticalWindowBuckets | 10 | 统计窗口的Buckets的数量,默认:10个 | |
metricsRollingPercentileEnabled | true | 是否开启监控统计功能,默认:true | |
requestLogEnabled | true | 是否开启请求日志 | |
requestCacheEnabled | true | 是否开启请求缓存 | |
熔断器配置 | circuitBreakerRequestVolumeThreshold | 20 | 主要用在小流量 |
circuitBreakerSleepWindowInMilliseconds | 5000ms | 熔断器默认工作时间,默认:5秒.熔断器中断请求5秒后会进入半打开状态,放部分流量过去重试 | |
circuitBreakerEnabled | true | 是否启用熔断器,默认true. 启动 | |
circuitBreakerErrorThresholdPercentage | 50 | 默认:50%。当出错率超过50%后熔断器启动 | |
circuitBreakerForceOpen | false | 是否强制开启熔断器阻断所有请求,默认:false,不开启 | |
circuitBreakerForceClosed | false | 是否允许熔断器忽略错误,默认false, 不开启 | |
线程池配置 | HystrixThreadPoolProperties.Setter().withCoreSize(int value) | 10 | 配置线程池大小,默认值10个 |
HystrixThreadPoolProperties.Setter().withMaxQueueSize(int value) | -1 | 配置线程值等待队列长度 |
详细参数
hystrix.command.default和hystrix.threadpool.default中的default为默认CommandKey
Command Properties
Execution相关的属性的配置:
hystrix.command.default.execution.isolation.strategy 隔离策略,默认是Thread, 可选Thread|Semaphore
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 命令执行超时时间,默认1000ms
hystrix.command.default.execution.timeout.enabled 执行是否启用超时,默认启用true
hystrix.command.default.execution.isolation.thread.interruptOnTimeout 发生超时是是否中断,默认true
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests 最大并发请求数,默认10,该参数当使用ExecutionIsolationStrategy.SEMAPHORE策略时才有效。如果达到最大并发请求数,请求会被拒绝。理论上选择semaphore size的原则和选择thread size一致,但选用semaphore时每次执行的单元要比较小且执行速度快(ms级别),否则的话应该用thread。semaphore应该占整个容器(tomcat)的线程池的一小部分。
Fallback相关的属性
这些参数可以应用于Hystrix的THREAD和SEMAPHORE策略
hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests 如果并发数达到该设置值,请求会被拒绝和抛出异常并且fallback不会被调用。默认10
hystrix.command.default.fallback.enabled 当执行失败或者请求被拒绝,是否会尝试调用hystrixCommand.getFallback() 。默认true
Circuit Breaker相关的属性
hystrix.command.default.circuitBreaker.enabled 用来跟踪circuit的健康性,如果未达标则让request短路。默认true
hystrix.command.default.circuitBreaker.requestVolumeThreshold 一个rolling window内最小的请求数。如果设为20,那么当一个rolling window的时间内(比如说1个rolling window是10秒)收到19个请求,即使19个请求都失败,也不会触发circuit break。默认20
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds 触发短路的时间值,当该值设为5000时,则当触发circuit break后的5000毫秒内都会拒绝request,也就是5000毫秒后才会关闭circuit。默认5000
hystrix.command.default.circuitBreaker.errorThresholdPercentage错误比率阀值,如果错误率>=该值,circuit会被打开,并短路所有请求触发fallback。默认50
hystrix.command.default.circuitBreaker.forceOpen 强制打开熔断器,如果打开这个开关,那么拒绝所有request,默认false
hystrix.command.default.circuitBreaker.forceClosed 强制关闭熔断器 如果这个开关打开,circuit将一直关闭且忽略circuitBreaker.errorThresholdPercentageMetrics相关参数
hystrix.command.default.metrics.rollingStats.timeInMilliseconds 设置统计的时间窗口值的,毫秒值,circuit break 的打开会根据1个rolling window的统计来计算。若rolling window被设为10000毫秒,则rolling window会被分成n个buckets,每个bucket包含success,failure,timeout,rejection的次数的统计信息。默认10000
hystrix.command.default.metrics.rollingStats.numBuckets 设置一个rolling window被划分的数量,若numBuckets=10,rolling window=10000,那么一个bucket的时间即1秒。必须符合rolling window % numberBuckets == 0。默认10
hystrix.command.default.metrics.rollingPercentile.enabled 执行时是否enable指标的计算和跟踪,默认true
hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds 设置rolling percentile window的时间,默认60000
hystrix.command.default.metrics.rollingPercentile.numBuckets 设置rolling percentile window的numberBuckets。逻辑同上。默认6
hystrix.command.default.metrics.rollingPercentile.bucketSize 如果bucket size=100,window=10s,若这10s里有500次执行,只有最后100次执行会被统计到bucket里去。增加该值会增加内存开销以及排序的开销。默认100
hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds 记录health 快照(用来统计成功和错误绿)的间隔,默认500ms
Request Context 相关参数
hystrix.command.default.requestCache.enabled 默认true,需要重载getCacheKey(),返回null时不缓存
hystrix.command.default.requestLog.enabled 记录日志到HystrixRequestLog,默认true
Collapser Properties 相关参数
hystrix.collapser.default.maxRequestsInBatch 单次批处理的最大请求数,达到该数量触发批处理,默认Integer.MAX_VALUE
hystrix.collapser.default.timerDelayInMilliseconds 触发批处理的延迟,也可以为创建批处理的时间+该值,默认10
hystrix.collapser.default.requestCache.enabled 是否对HystrixCollapser.execute() and HystrixCollapser.queue()的cache,默认true
ThreadPool 相关参数
线程数默认值10适用于大部分情况(有时可以设置得更小),如果需要设置得更大,那有个基本得公式可以follow:
requests per second at peak when healthy × 99th percentile latency in seconds + some breathing room
每秒最大支撑的请求数 (99%平均响应时间 + 缓存值) 比如:每秒能处理1000个请求,99%的请求响应时间是60ms,那么公式是:(0.060+0.012)基本得原则时保持线程池尽可能小,他主要是为了释放压力,防止资源被阻塞。当一切都是正常的时候,线程池一般仅会有1到2个线程激活来提供服务
hystrix.threadpool.default.coreSize 并发执行的最大线程数,默认10
hystrix.threadpool.default.maxQueueSize BlockingQueue的最大队列数,当设为-1,会使用SynchronousQueue,值为正时使用LinkedBlcokingQueue。该设置只会在初始化时有效,之后不能修改threadpool的queue size,除非reinitialising thread executor。默认-1。
hystrix.threadpool.default.queueSizeRejectionThreshold 即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝。因为maxQueueSize不能被动态修改,这个参数将允许我们动态设置该值。if maxQueueSize == -1,该字段将不起作用
hystrix.threadpool.default.keepAliveTimeMinutes 如果corePoolSize和maxPoolSize设成一样(默认实现)该设置无效。如果通过plugin(https://github.com/Netflix/Hystrix/wiki/Plugins)使用自定义实现,该设置才有用,默认1.
hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds 线程池统计指标的时间,默认10000
hystrix.threadpool.default.metrics.rollingStats.numBuckets 将rolling window划分为n个buckets,默认10