背景
为了防止服务消费链(多级服务之间的调用)上因某个服务出现故障,而导致级联故障,进而造成整个系统不可用(简称为:雪崩效应),推出了熔断、降级的处理方式:Hystrix断路器(类似生活中电路保险丝)来解决这些潜在问题。
熔断、降级的区别?
- 熔断:
暂时切断对下游服务的调用,直接快速返回错误的响应信息,当检测到该下游服务节点调用响应正常后再恢复消费链路。
关闭状态:服务正常放行。
打开状态:默认10秒内错误率达到50%,则打开,后续服务直接拒绝。
半开状态:打开后默认5秒后,半开状态,运行部分流量通过,如果没有改善,继续打开。
- 降级
是指服务资源不够的时候,关闭部分不重要的资源,以维持重要服务正常运行的机制。
Hystrix隔离模式
信号量模式
特点:同步调用、开销小
线程池模式
如果线程池已满调用将被立即拒绝,默认不采用排队.加速失败判定时间。
特点:支持超时、开销大、功能强。
参考:https://www.jianshu.com/p/e1a4d3bdf7c4
Spring 集成
引用
这里注意使用的版本,我使用的是springboot 2.1.5,springcloud Greenwich.SR2。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
测试类
为了方便测试,我们设置熔断超时时间1秒。
如果5秒内,请求达到了4个,错误率达到50%以上,就开启跳闸,3秒以后再调用,会再执行一次业务方法
/**
* 启动类
*
* @author tianyunperfect
* @date 2021/03/11
*/
@SpringBootApplication
@EnableHystrix
@RestController
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
/**
* hystrix测试
*
* @return {@link String}* @throws InterruptedException 中断异常
*/
@GetMapping("/test")
@HystrixCommand(fallbackMethod = "fallBack",
commandProperties = {
//熔断超时时间1秒
//如果5秒内,请求达到了4个,错误率达到50%以上,就开启跳闸,3秒以后再调用,会再执行一次业务方法
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "5000"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "4"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "3000")
})
public String hystrixTest() throws InterruptedException {
Thread.sleep(3000);
return "Welcome Hystrix";
}
/**
* 熔断保护
* 注解在哪个方法上,返回值和方法参数一定要一致。
*
* @return {@link String}
*/
private String fallBack() {
return "请求失败,熔断保护";
}
}
线程池配置示例。
@HystrixCommand(fallbackMethod = "error", commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "4000"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50")
},
threadPoolProperties = { // hystrix 中线程池配置
@HystrixProperty(name = "coreSize", value = "1"),
@HystrixProperty(name = "maxQueueSize", value = "10"),
@HystrixProperty(name = "keepAliveTimeMinutes", value = "1000"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "8"),
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "12"),
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1500")
})
测试结果
Python测试代码
import datetime
import requests
for i in range(10000):
start = datetime.datetime.now()
requests.get("http://localhost:8881/test")
end = datetime.datetime.now()
print(str(datetime.datetime.now()) + ": " + str(end - start))
测试效果,
- 5秒后开启熔断
- 3秒后放行一个