目录
- 一、概述
- (1)服务降级(fallback)
- (2)服务熔断(break)
- (3)服务限流(flowlimit)
- 二、服务降级
- (1)在服务端启动策略
- (2)在客户端启用策略
- (3)全局fallback
- (4)使用fallbackFactory(常用)
- 三、服务熔断
一、概述
是一个用于处理分布式系统的延迟和容错的开源库。
断路器:是一种开关装置。当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出无法处理的异常,这样就保证了调用方的线程不会被长时间、不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
(1)服务降级(fallback)
当服务器忙时,不让客户端处于一直等待状态,并立刻返回一个友好提示。
(2)服务熔断(break)
服务不可用时,停止对该服务的调用,过一段时间,直到完全恢复服务提供。
(3)服务限流(flowlimit)
严禁一窝蜂的过来拥挤,大家排队,一秒钟只允许通过 N 个,有序进行。
二、服务降级
- 引入pom
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix</artifactId>
</dependency>
(1)在服务端启动策略
- 在启动类添加
@EnableCircuitBreaker
注解 - 设置服务降级策略(出错或者大于4秒时进入服务降级策略)
@Service
public class PaymentService {
/**
* 成功
* @param id
* @return
*/
public String paymentInfo_OK(Integer id) {
return "线程池:" + Thread.currentThread().getName() + " paymentInfo_OK,id: " + id + "\t" + "好好好";
}
/**
* timeout超时
* @param id
* @return
*/
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
//4秒钟以内就执行正常的业务逻辑,反之执行降级方法
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "4000")
})
public String paymentInfo_TimeOut(Integer id) { ;
try {
TimeUnit.MILLISECONDS.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + " paymentInfo_TimeOut,id: " + id + "\t" + "等等等";
}
/**
* 兜底
*/
public String paymentInfo_TimeOutHandler(Integer id) {
return "线程池:" + Thread.currentThread().getName() + "出现错误,请稍后重试" + id + "\t";
}
}
(2)在客户端启用策略
- 主启动类添加
@EnableHystrix
注解 - 修改配置文件
server:
port: 80
spring:
application:
name: cloud-provider-hystrix-order
eureka:
client:
register-with-eureka: true #示表不向注册中心注册自己
fetch-registry: true #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
####################以下配置需要新增(ribbon相关配置和Feign超时相关)##################
#全局配置
# 请求连接的超时时间 默认的时间为 1 秒
ribbon:
ConnectTimeout: 5000
# 请求处理的超时时间
ReadTimeout: 5000
# feign 配置
feign:
hystrix:
enabled: true
# hystrix 配置
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 60000
- controller
@RestController
public class OrderHystrixController {
@Autowired
private PaymentHystrixService paymentHystrixService;
@GetMapping("/consumer/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id) {
return paymentHystrixService.paymentInfo_OK(id);
}
// 添加服务降级相关配置
@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000") //1钟以内就是正常的业务逻辑
})
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
return paymentHystrixService.paymentInfo_TimeOut(id);
}
//服务降级方法
public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {
return "我是消费者80";
}
}
(3)全局fallback
- 添加@DefaultProperties注解
- 添加@HystrixCommand注解
@RestController
@DefaultProperties(defaultFallback = "paymentTimeOutFallbackMethod")
public class OrderHystrixController {
@Autowired
private PaymentHystrixService paymentHystrixService;
@GetMapping("/consumer/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id) {
return paymentHystrixService.paymentInfo_OK(id);
}
// 添加服务降级相关配置
@HystrixCommand
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
return paymentHystrixService.paymentInfo_TimeOut(id);
}
//全局服务降级方法(不能有参数)
public String paymentTimeOutFallbackMethod() {
return "我是,全局服务降级方法";
}
}
(4)使用fallbackFactory(常用)
三、服务熔断
当出现错误或超时时,会首先启动服务降级,当次数达到一定的阈值时,会启动熔断机制(所有请求都不会转发),一段时间后,进入半开状态,让一个请求进行转发,若成功则关闭服务熔断。
- service
@Service
public class PaymentService{
//服务熔断
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_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"), //失败率达到多少后跳闸,此处为60%(上面配置意思是:10秒钟内,10次请求,失败率60%就不让用了)
// 具体需要配置哪些参数,在 HystrixCommandProperties.java 类中
})
public String paymentCircuitBreaker(@PathVariable("id") Integer id){
if (id < 0){
throw new RuntimeException("*****id 不能负数");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName()+"\t"+"调用成功,流水号:"+serialNumber;
}
//服务降级
public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){
return "id 不能负数,请稍候再试,(┬_┬)/~~ id: " +id;
}
}
- controller
//===服务熔断
@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id){
String result = paymentService.paymentCircuitBreaker(id);
log.info("*******result:"+result);
return result;
}
- 常用配置
@HystrixCommand(fallbackMethod = "str_fallbackMethod",
groupKey = "strGroupCommand",
commandKey = "strCommand",
threadPoolKey = "strThreadPool",
commandProperties = {
//设置执行隔离策略,THREAD 表示线程池 SEMAPHORE:信号量隔离 默认为THREAD线程池
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
// 当隔离策略选择信号池隔离的时候,用来设置信号池的大小(最大并发数)
@HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "10"),
// 配置命令执行的超时时间
@HystrixProperty(name = "execution.isolation.thread.timeoutinMilliseconds", value = "10"),
// 是否启用超时时间
@HystrixProperty(name = "execution.timeout.enabled", value = "true"),
// 执行超时的时候是否中断
@HystrixProperty(name = "execution.isolation.thread.interruptOnTimeout", value = "true"),
// 执行被取消的时候是否中断
@HystrixProperty(name = "execution.isolation.thread.interruptOnCancel", value = "true"),
// 允许回调方法执行的最大并发数
@HystrixProperty(name = "fallback.isolation.semaphore.maxConcurrentRequests", value = "10"),
// 服务降级是否启用,是否执行回调函数
@HystrixProperty(name = "fallback.enabled", value = "true"),
// 设置断路器是否起作用。
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
// 该属性用来设置在滚动时间窗中,断路器熔断的最小请求数。例如,默认该值为 20 的时候,
// 如果滚动时间窗(默认10s)内仅收到了19个请求,及时这19个请求都失败了,断路也不会打开。
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),
// 该属性用来设置在滚动时间窗中,表示在滚动时间窗中,在请求数量超过 circuitBreaker.requestVolumeThreshold 的情况下,
// 如果错误请求数的百分比超过 50,就把断路器设置为"打开"状态,否则就设置为"关闭"状态
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
// 该属性用来设置当断路器打开之后的休眠时间窗。休眠时间窗结束之后,会将断路器置为"半开"状态,
// 尝试熔断的请求命令,如果依然失败就将断路器继续设置为"打开"状态,如果成功就设置为"关闭"状态
@HystrixProperty(name = "circuitBreaker.sleepWindowinMilliseconds", value = "5000"),
// 断路器强制打开
@HystrixProperty(name = "circuitBreaker.forceOpen", value = "false"),
// 断路器强制关闭
@HystrixProperty(name = "circuitBreaker.forceClosed", value = "false"),
// 滚动时间窗设置,该时间用于断路器判断健康度时,需要收集信息的持续时间
@HystrixProperty(name = "metrics.rollingStats.timeinMilliseconds", value = "10000"),
// 该属性用来设置滚动时间窗统计指标信息时,划分"桶"的数量,断路器在手机指标信息的时候会根据设置的时间窗长度拆分成多个"桶"来累计各度量值,每个
// "桶"记录了一段时间内的采集指标。比如 10 秒内拆分成 10 个"桶'收集这样,所以 timeinMilliseconds 必须能被 numBuckets 整除。否则会抛异常
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),
// 该属性用来设置对命令执行的延迟是否采用百分位数来跟踪和计算。如果设置为 false,name所有的概要统计都将返回-1
@HystrixProperty(name = "metrics.rollingPercentile.enabled", value = "false"),
// 该属性用来设置百分位统计的滚动窗口的持续时间,单位为毫秒
@HystrixProperty(name = "metrics.rollingPercentile.timeInMilliseconds", value = "60000"),
// 该属性用来设置百分位统计滚动窗口中使用 "桶" 的数量
@HystrixProperty(name = "metrics.rollingPercentile.numBuckets", value = "60000"),
// 该属性用来设置在执行过程中每个"桶"中保留的最大执行次数。如果在滚动时间窗内发生超过该设定值的执行次数
// 就从最初的位置开始重写。例如,将该值设置为100,滚动窗口为10秒,若在10秒内一个"桶"中发生了500次执行,
// 那么该"桶"中只保留最后的100次执行的统计。另外,增加该值的大小将会增加内存量的消耗,并增加排序百分位数所需的计算时间
@HystrixProperty(name = "metrics.rollingPercentile.bucketSize", value = "100"),
// 该属性用来设置采集意向断路器状态的健康快照(请求的成功、错误百分比)的间隔等待时间
@HystrixProperty(name = "metrics.healthSnapshot.intervalinMilliseconds", value = "500"),
// 是否开启请求缓存
@HystrixProperty(name = "requestCache.enabled", value = "true"),
// HystrixCommand 的执行和事件是否打印日志到 HystrixRequestLog 中
@HystrixProperty(name = "requestLog.enabled", value = "true")
},
threadPoolProperties = {
// 该参数用来设置执行命令线程池的核心线程数,该值也就是命令执行的最大并发量
@HystrixProperty(name = "coreSize", value = "10"),
// 该参数用来设置线程池的最大队列大小。当设置为 -1 时,线程池将使用 SynchronousQueue 实现的队列,否则将使用 LinkedBlockingQueue 实现的队列
@HystrixProperty(name = "maxQueueSize", value = "-1"),
// 该参数用来为队列设置拒绝阈值。通过该参数,即使队列没有达到最大值也能拒绝请求。该参数主要是对 LinkedBlockingQueue 队列的补充,因为LinkedBlockingQueue
// 队列不能动态修改它的对象大小,而通过该属性就可以调整拒绝请求的队列大小了
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "5")
}
)