SpringCloud 使用Hystrix实现服务降级、服务熔断
分布式系统面临的问题
复杂的分布式体系结构中的应用程序,有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。
什么是服务雪崩
雪崩效应:是一种因服务"提供者"的不可用导致服务"调用者"的不可用,并将不可用逐渐放大的过程。
简单的说,服务堆积在同一个线程池中,因为所有的请求都是同一个线程池进行处理,这时候如果在高并发情况下,所有的请求全部访问同一个接口,
这时候可能会导致其他服务没有线程进行接受请求,这就是服务雪崩效应效应。
导致服务雪崩的原因大概有这几个:
- 某几个机器故障:例如机器的硬驱动引起的错误,或者一些特定的机器上出现一些的bug(如,内存中断或者死锁)。
- 服务器负载发生变化:某些时候服务会因为用户行为造成请求无法及时处理从而导致雪崩,例如阿里的双十一活动,若没有提前增加机器预估流量则会造服务器压力会骤然增大二挂掉。
- 人为因素:比如代码中的路径在某个时候出现bug
服务雪崩的解决方案
5种:服务降级、服务熔断、服务隔离、限流模式、超时机制
1、服务降级:在高并发情况下,防止用户一直等待(返回一个友好的提示,直接给客户端,不会去处理请求,调用fallBack本地方法),目的是为了用户体验。 秒杀---当前请求人数过多,请稍后重试
2、服务熔断:熔断机制目的为了保护服务,在高并发的情况下,如果请求达到一定极限(可以自己设置阈值),如果流量超出了设置阈值,直接拒绝访问,保护当前服务。使用服务降级方式返回一个友好提示,服务熔断和服务降级一起使用。
熔断的设计主要参考了hystrix的做法,分为3个模块:熔断请求判断算法、熔断恢复机制、熔断报警
- 熔断请求判断机制算法:使用无锁循环队列计数,每个熔断器默认维护10个bucket,每1秒一个bucket,每个blucket记录请求的成功、失败、超时、拒绝的状态,默认错误超过50%且10秒内超过20个请求进行中断拦截。
- 熔断恢复:对于被熔断的请求,每隔5s允许部分请求通过,若请求都是健康的(RT<250ms)则对请求健康恢复。
- 熔断报警:对于熔断的请求打日志,异常请求超过某些设定则报警。
3、服务隔离:有2种方式:线程池隔离和信号量隔离。
- 线程池隔离:每个服务接口,都有自己独立的线程池,每个线程池互不影响。
- 信号量隔离:使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,当请求进来时先判断计数器的数值,若超过设置的最大线程个数则拒绝该请求,若不超过则通行,这时候计数器+1,请求返回成功后计数器-1。
4、限流模式:上述都属于出错后的容错处理机制,而限流模式则可以称为预防模式。限流模式主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。这种模式不能解决服务依赖的问题,只能解决系统整体资源分配问题,因为没有被限流的请求依然有可能造成雪崩效应。
5、超时机制:超时分两种:请求的等待超时、请求运行超时
- 等待超时:在任务入队列时设置任务入队列时间,并判断队头的任务入队列时间是否大于超时时间,超过则丢弃任务。
- 运行超时:直接可使用线程池提供的get方法
Hystrix简介
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能保证在一个依赖出问题的情况下,不会导致整个服务失败,避免出现级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开发装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
在SpringCloud中断路器组件就是Hystrix。Hystrix也是Netflix套件的一部分。它的功能是,当对某个服务的调用在一定的时间内(默认10s),有超过一定次数(默认20次)并且失败率超过一定值(默认50%),该服务的断路器会打开。返回一个由开发者设定的fallback。fallback可以是另一个由Hystrix保护的服务调用,也可以是固定的值。fallback也可以设计成链式调用,先执行某些逻辑,再返回fallback。
Hystrix的作用:
- 服务降级(Fallback):比如当服务器忙,请稍后再试,不让客户端等待并立刻返回一个友好提示,Fallback,会发生降级的几种情况:程序运行异常、超时、服务熔断触发服务降级。
- 服务熔断(Break):类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示。三个步骤先进行服务的降级、进而熔断、恢复调用链路。
- 实时的监控:会持续地记录所有通过Hystrix发起的请求执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少成功,多少失败等。
- 服务限流(Flowlimit):比如秒杀高并发等操作,严禁一窝蜂的过来拥挤、安排大家排队,一秒钟N个请求,有序进行。
SpringCloud使用Hystrix
服务提供者集成hystrix
创建服务提供者,模块名cloud-hystrix-service
1、添加依赖
<!--boot web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 添加eureka客户端的依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2、配置application.yml
server:
port: 7666
spring:
application:
name: cloud-hystrix-service
#eureka配置
eureka:
client:
#表示是否将自己注册进eureka 默认为true
register-with-eureka: true
#是否从EurekaServer中抓取已有的注册信息,默认为true,单点无所谓,集群必须设置true才能和ribbon使用负载均衡
fetch-registry: true
service-url:
#集群配置
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
3、启动类
@EnableDiscoveryClient
@SpringBootApplication
public class HystrixApp {
public static void main(String[] args) {
SpringApplication.run(HystrixApp.class, args);
}
}
4、PaymentController
@RequestMapping("/payment")
@RestController
public class PaymentController {
@RequestMapping("/paymentOk")
public Map<String, Object> paymentOk(@RequestParam("userId") Integer userId) {
Map<String, Object> resultMap = new HashMap();
resultMap.put("code", 200);
resultMap.put("message", "paymentOk调用成功");
resultMap.put("userId", userId);
return resultMap;
}
}
引入hystrix依赖
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
启动类必须添加注解:@EnableCircuitBreaker ,用于开启断路器,激活@HystrixCommand注解
服务降级配置
1、超时的服务降级
改造后的PaymentController如下:
@RequestMapping("/payment")
@RestController
public class PaymentController {
//fallbackMethod是降级的方法名,表示异常了由该方法进行兜底
@HystrixCommand(fallbackMethod = "paymentOkFallbackHandler", commandProperties = {
//value表示当前线程的超时时间为3s
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")})
@RequestMapping("/paymentOk")
public Map<String, Object> paymentOk(@RequestParam("userId") Integer userId) throws InterruptedException {
//休眠时间
Thread.sleep(1000);
Map<String, Object> resultMap = new HashMap();
resultMap.put("code", 200);
resultMap.put("message", "paymentOk调用成功");
resultMap.put("userId", userId);
return resultMap;
}
//方法入参和返回参数都必须与被服务降级的方法一致
public Map<String, Object> paymentOkFallbackHandler(Integer userId) {
Map<String, Object> resultMap = new HashMap();
resultMap.put("code", 200);
resultMap.put("message", "paymentOk超时,服务降级了");
resultMap.put("userId", userId);
return resultMap;
}
}
我们先设置线程休眠1s,访问 http://localhost:7666/payment/paymentOk?userId=100
再设置线程休眠5s,然后再访问,结果如下:
说明我们的配置起作用了。
2、运行异常的服务降级
@RequestMapping("/payment")
@RestController
public class PaymentController {
@HystrixCommand(fallbackMethod = "paymentOkFallbackHandler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")})
@RequestMapping("/paymentOk")
public Map<String, Object> paymentOk(@RequestParam("userId") Integer userId){
//异常错误的演示代码
int a = 10/0;
Map<String, Object> resultMap = new HashMap();
resultMap.put("code", 200);
resultMap.put("message", "paymentOk调用成功");
resultMap.put("userId", userId);
return resultMap;
}
//方法入参和返回参数都必须与被服务降级的方法一致
public Map<String, Object> paymentOkFallbackHandler(Integer userId) {
Map<String, Object> resultMap = new HashMap();
resultMap.put("code", 200);
resultMap.put("message", "paymentOk超时,服务降级了");
resultMap.put("userId", userId);
return resultMap;
}
}
重启服务再调用,直接就进行了降级服务。
服务消费者集成hystrix
创建服务调用者,模块名cloud-openfeign-consumer-service,调用cloud-hystrix-service
1、添加依赖
<!--boot web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 添加eureka客户端的依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<exclusions>
<!-- 如果-->
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- SpringCloud Feign在Hoxton.M2 RELEASED版本之后不再使用Ribbon而是使用spring-cloud-loadbalancer -->
<!-- ribbon相关的依赖不能与loadbalancer 同时存在,否则奇奇怪怪的问题一大堆, 可能连应用都起不来 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
<!--openfeign-core包含了ribbon,先排除掉再进行单独的引入-->
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
2、application.yml
server:
port: 7755
spring:
application:
name: cloud-openfeign-consumer-service
#eureka配置
eureka:
client:
#表示是否将自己注册进eureka 默认为true
register-with-eureka: true
#是否从EurekaServer中抓取已有的注册信息,默认为true,单点无所谓,集群必须设置true才能和ribbon使用负载均衡
fetch-registry: true
service-url:
#集群配置
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
# open feign 配置
feign:
client:
config:
# feign请求默认配置
default:
#连接超时时间
connectTimeout: 2000
#读超时时间
readTimeout: 5000
3、启动类
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class OpenFeignConsumerApp {
public static void main(String[] args) {
SpringApplication.run(OpenFeignConsumerApp.class, args);
}
}
4、feign接口
@FeignClient(name = "cloud-hystrix-service")
public interface PaymentFeign {
@RequestMapping("/payment/paymentOk")
Map<String, Object> paymentOk(@RequestParam("userId") Integer userId);
}
5、PaymentController
@RequestMapping("/payment")
@RestController
public class PaymentController {
@Autowired
private PaymentFeign paymentFeign;
@RequestMapping("/paymentOk")
public Map<String,Object> paymentOk(@RequestParam("userId") Integer userId){
return paymentFeign.paymentOk(userId);
}
}
模拟OpenFeign调用超时
1)将cloud-hystrix-service的paymentOk方法的休眠时间设置长一点
2)将我们上面application.yml配置的feign.client.config.default.readTimeout设置短点
服务重启完毕后,我们访问:http://localhost:7755/payment/paymentOk?userId=100
查看控制台:
确实读超时了。
OpenFeign调用的服务降级配置
注:如果仅仅是内部的服务降级,跟上面服务提供者cloud-hystrix-service的配置是一样的。
这里我们着重看下OpenFeign调用出现异常时如何处理。
1、添加hystrix依赖:
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、feign开启hystrix的支持
feign:
hystrix:
enabled: true # 默认是false
3、关于服务的降级,是消费者服务去调用生产者服务,如果生产者服务出现宕机或者关闭,那我们就要对消费者服务进行服务降级处理,与生产者服务没有关系,只需要为Feign客户端定义的接口添加一个服务降级处理的实现类即可实现解耦。为了防止与业务逻辑与代码混在一块,看起来特别混乱,所以要新建一个类PaymentFallbackService,实现该业务类PaymentFeign接口,统一为接口里面的方法进行异常处理。
/**
* 实现PaymentFeign接口,作为PaymentFeign服务降级的配置
*/
@Component
public class PaymentFallbackService implements PaymentFeign {
@Override
public Map<String, Object> paymentOk(Integer userId) {
Map<String, Object> resultMap = new HashMap();
resultMap.put("code", 200);
resultMap.put("message", "paymentOk调用异常, 进行服务降级,请稍后重试");
resultMap.put("userId", userId);
return resultMap;
}
}
也要在PaymentFeign业务类上加上@FeignClient注解,表示FeignClient注解的作用目标在接口上
//fallback属性当服务出现故障时,该类进行服务降级处理
@FeignClient(name = "cloud-hystrix-service", fallback = PaymentFallbackService.class)
public interface PaymentFeign {
@RequestMapping("/payment/paymentOk")
Map<String, Object> paymentOk(@RequestParam("userId") Integer userId);
}
我们重启服务,访问:http://localhost:7755/payment/paymentOk?userId=100
服务降级成功。
全局默认的服务降级
以服务提供者(cloud-hystrix-service)为例进行演示。
1)在PaymentController类上添加DefaultProperties注解,配置默认的服务降级方法
2)在那些需要对服务进行降级处理的方法上添加@HystrixCommand注解,但是不用再声明降级服务方法名
3)降级服务方法不应有参数
4)降级服务返回值与原服务返回值保持一致
//PaymentController里默认的全局的服务降级配置
@DefaultProperties(defaultFallback = "paymentOkFallbackHandler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
})
@RequestMapping("/payment")
@RestController
public class PaymentController {
//@HystrixCommand标记需要对该方法进行服务降级处理
@HystrixCommand
@RequestMapping("/paymentOk")
public Map<String, Object> paymentOk(@RequestParam("userId") Integer userId) throws InterruptedException {
Thread.sleep(2000);
Map<String, Object> resultMap = new HashMap();
resultMap.put("code", 200);
resultMap.put("message", "paymentOk调用成功");
resultMap.put("userId", userId);
return resultMap;
}
//返回值与原方法一致,但是方法不能有入参
public Map<String, Object> paymentOkFallbackHandler() {
Map<String, Object> resultMap = new HashMap();
resultMap.put("code", 200);
resultMap.put("message", "paymentOk超时,服务降级全局了");
return resultMap;
}
}
服务熔断
什么是熔断机制
熔断机制是应对雪崩效应的一种微服务链路保护机制,当扇出链路的某一个微服务出错不可用或者响应时间太长,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息,当检测到该节点微服务调用响应正常后,恢复调用链路。
在Spring Cloud框架里,熔断机制通过Hystrix实现。Hystrix会监控微服务调用的状况,当失败的调用到一定的阈值,缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是@HystrixCommand。
代码实现
以服务提供者(cloud-hystrix-service)为例进行演示。
1、我们在PaymentController中添加以下代码:
@RequestMapping("/hystrix")
@RestController
public class HystrixController {
@HystrixCommand(fallbackMethod = "hystrixCircuitBreaker_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"),// 失败率达到多少后跳闸
})
@RequestMapping("/hcBreaker")
public String hystrixCircuitBreaker(@RequestParam("id") Integer id) {
if (id < 0) {
throw new RuntimeException("******id 不能负数");
}
String serialNumber = UUID.randomUUID().toString().replaceAll("-", "");
return Thread.currentThread().getName() + "\t" + "调用成功,流水号: " + serialNumber;
}
//兜底降级的方法
public String hystrixCircuitBreaker_fallback(Integer id) {
return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~ id: " + id;
}
}
2、Hystrix断路器使用时最常用的三个重要指标参数
在微服务中使用Hystrix 作为断路器时,通常涉及到以下三个重要的指标参数(@HystrixProperties配置)
1)circuitBreaker.sleepWindowInMilliseconds
断路器的快照时间窗,也叫做窗口期。可以理解为一个触发断路器的周期时间值,默认为10秒(10000)。
2)circuitBreaker.requestVolumeThreshold
断路器的窗口期内触发断路的请求阈值,默认为20。换句话说,假如某个窗口期内的请求总数都不到该配置值,那么断路器连发生的资格都没有。断路器在该窗口期内将不会被打开。
3)circuitBreaker.errorThresholdPercentage
断路器的窗口期内能够容忍的错误百分比阈值,默认为50(也就是说默认容忍50%的错误率)。打个比方,假如一个窗口期内,发生了100次服务请求,其中50次出现了错误。在这样的情况下,断路器将会被打开。在该窗口期结束之前,即使第51次请求没有发生异常,也将被执行fallback逻辑。
综上所述,在以上三个参数缺省的情况下,Hystrix断路器触发的默认策略为:
在10秒内,发生20次以上的请求时,假如错误率达到50%以上,则断路器将被打开。(当一个窗口期过去的时候,断路器将变成半开(HALF-OPEN)状态,如果这时候发生的请求正常,则关闭,否则又打开)
3、熔断三大类型
熔断打开:请求不再调用当前服务,内部设置一般为MTTR(平均故障处理时间),当打开时长达到所设时钟则进入半熔断状态。
熔断关闭:熔断关闭不会对服务进行熔断。
熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则认为当前服务恢复正常,关闭熔断。
4、断路器开启或者关闭的条件有哪些?
1)当满足一定的阈值的时候(默认10秒钟超过20个请求次数)
2)当失败率达到一定的时候(默认10秒钟超过50%的请求次数)
3)当达到以上阈值,断路器将会开启
4)当开启的时候,所有请求都不会进行转发
5)一段时间之后(默认5秒),这个时候断路器是半开状态,会让其他一个请求进行转发
6)如果成功,断路器会关闭,若失败,继续开启重复第4步和第5步
5、断路器打开之后会发生什么?
1)再有请求调用的时候,将不会调用主逻辑,而是直接调用降级fallback,通过断路器,实现了自动地发现错误并将降级逻辑切换为主逻辑,减少响应延迟的效果。
2)原来的主逻辑要如何恢复呢?
对于这一问题,Hystrix也为我们实现了自动恢复功能,当断路器打开,对主逻辑进行熔断之后,Hystrix会启动一个休眠时间窗,在这个时间窗内,降级逻辑是临时的成为主逻辑。当休眠时间窗到期,断路器将进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回,那么断路器将继续闭合,主逻辑恢复,如果这次请求依然有问题,断路器继续进入打开状态,休眠时间窗重新计时。
Hystrix主要注解说明
@HystrixCommand
开发要求:
- 降级服务返回值与原服务返回值保持一致
- 降级服务的参数与原服务参数保持一致
- fallbackMethod属性查找的是参数、返回值和原服务保持一致的降级方法(一般使用此属性设置降级方法)
- defaultFallback属性是查找返回值和原服务一致且参数为空的降级方法
@HystrixCommand注解的各个参数
hystrix.command.default和hystrix.threadpool.default中的default为默认CommandKey
Command Properties
1)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)的线程池的一小部分。
2)Fallback相关的属性
这些参数可以应用于Hystrix的THREAD和SEMAPHORE策略
hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests 如果并发数达到该设置值,请求会被拒绝和抛出异常并且fallback不会被调用。默认10
hystrix.command.default.fallback.enabled 当执行失败或者请求被拒绝,是否会尝试调用hystrixCommand.getFallback() 。默认true
3)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.errorThresholdPercentage
4)Metrics相关参数
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
5)Request Context 相关参数
hystrix.command.default.requestCache.enabled 默认true,需要重载getCacheKey(),返回null时不缓存
hystrix.command.default.requestLog.enabled 记录日志到HystrixRequestLog,默认true
6)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
7)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
@DefaultProperties
1)该注解标注在类上面,定义默认的回退方法
2)原服务标注@HystrixCommand注解,但是不用再声明降级服务方法名
3)降级服务方法不应有参数
4)降级服务返回值与原服务返回值保持一致
Hystrix的图形化Dashboard实时监控
Hystrix除了隔离依赖服务的调用以外,还提供了准时的调用监控(Hystrix Dashboard)Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。
hystrix-dashboard服务
新建module,名称为cloud-consumer-hystrix-dashboard服务,第一步修改pom.xml文件。主要是引入hystrix dashboard的依赖。如下图:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--hystrix dashboard-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
application.yml
server:
port: 7777
hystrix:
dashboard:
#需要填写我们希望在监控面板中查看的服务的的ip或域名,没配置会提示:Unable to connect to Command Metric Stream
proxy-stream-allow-list:
- localhost
- 127.0.0.1
新建主启动类,主要是加上@EnableHystrixDashboard注解,如下图:
@EnableHystrixDashboard //开启hystrix dashboard 监控
@SpringBootApplication
public class HystrixDashboardApp {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApp.class, args);
}
}
我们启动该服务,访问http://localhost:7777/hystrix,出现如下成功界面,说明配置成功。如下图:
断路器服务
断路器服务需要进行改造:
1、除了添加spring-cloud-starter-netflix-hystrix依赖外,还需要添加actuator依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、application.yml修改
# 配置Hystrix Metrics Stream
management:
endpoints:
web:
exposure:
include: hystrix.stream
3、测试验证
在hystrix dashboard监控页面中,输入:
注意:这里有一个细节需要注意,要访问/hystrix.stream 接口,首先得访问消费者工程中的任意一个其他接口,否则直接访问/hystrix.stream 接口时会输出出一连串的 ping: ping: …,先访问 consumer 中的任意一个其他接口,然后再访问/hystrix.stream 接口即可;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!