刚开始参加工作的时候,看公司的SOA框架描述什么降级和熔断,当时我百脸懵逼,什么鬼。就写几个代码,还要熔断和降级,难道在代码中安装了保险丝,代码执行着突然不爽还要降一级吗,有病吧!笑哭了!
曾几何时欠下的技术债终于要还了,最近项目中使用到了Netflix公司的开源组件Hystrix,于是研究了一下,对降级和熔断有些理解了。
下面通过Hystrix的两个例子来理解降级和熔断,更多关于Hystrix的内容,大家Google去吧。
降级(fallback)
MorningService.java
public class MorningService {
/**
* 超时
*/
public void timeout() {
int j = 0;
while (true) {
j++;
}
}
}
HystrixFallbackTest.java
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;
import org.junit.Test;
import java.io.IOException;
public class HystrixFallbackTest extends HystrixCommand<String> {
private final String name;
private MorningService morningService;
public HystrixFallbackTest(String name, MorningService morningService) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("FallbackGroup"))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(10000))); // 10秒超时哦
this.name = name;
this.morningService = morningService;
}
@Override
protected String run() throws Exception {
/**
* 超时触发fallback
*/
morningService.timeout();
return name;
}
/**
* Hystrix的降级方法
* @return
*/
@Override
protected String getFallback() {
return "fallback: " + name;
}
public static class UnitTest {
@Test
public void testFallback() throws IOException {
System.out.println(new HystrixFallbackTest("Morning", new MorningService()).execute());
}
}
}
执行上面的Test方法,在run方法里正常执行超过10秒就timeout了,走降级方法fallbck(),打印出的内容是:
fallback: Morning
1
降级就是在执行主流程时,主流程突然出现意外执行不下去了,那就执行另外一个方法让主流程看起来是正常的(这个方法通常就是降级方法,似乎有些牵强)。
熔断(circuit breaker)
保险丝:电路中正确安置保险丝,保险丝就会在电流异常升高到一定的高度和热度的时候,自身熔断切断电流,保护了电路安全运行。(来自百度百科)
熔断就跟保险丝一样,当一个服务请求并发特别大,服务器已经招架不住了,调用错误率飙升,当错误率达到一定阈值后,就将这个服务熔断了。熔断之后,后续的请求就不会再请求服务器了,以减缓服务器的压力。
来一个栗子吧:
HystrixCircuitBreakerTest.java
import com.netflix.hystrix.*;
import org.junit.Test;
import java.io.IOException;
public class HystrixCircuitBreakerTest extends HystrixCommand<String> {
private final String name;
private MorningService morningService;
public HystrixCircuitBreakerTest(String name, MorningService morningService) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("CircuitBreakerTestGroup"))
.andCommandKey(HystrixCommandKey.Factory.asKey("CircuitBreakerTestKey"))
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("CircuitBreakerTest"))
.andThreadPoolPropertiesDefaults( // 配置线程池
HystrixThreadPoolProperties.Setter()
.withCoreSize(200) // 配置线程池里的线程数,设置足够多线程,以防未熔断却打满threadpool
)
.andCommandPropertiesDefaults( // 配置熔断器
HystrixCommandProperties.Setter()
.withCircuitBreakerEnabled(true) // 熔断器在整个统计时间内是否开启的阀值
.withCircuitBreakerRequestVolumeThreshold(3) // 至少有3个请求才进行熔断错误比率计算
.withCircuitBreakerErrorThresholdPercentage(50) //当出错率超过50%后熔断器启动
.withMetricsRollingStatisticalWindowInMilliseconds(5000) // 统计滚动的时间窗口
.withCircuitBreakerSleepWindowInMilliseconds(2000) // 熔断器工作时间,超过这个时间,先放一个请求进去,成功的话就关闭熔断,失败就再等一段时间
)
);
this.name = name;
this.morningService = morningService;
}
@Override
protected String run() throws Exception {
int num = Integer.valueOf(name);
if(num % 2 == 0) { // 直接返回
return name;
} else {
morningService.timeout(); // 无限循环模拟超时
}
return name;
}
/**
* Whether or not your command has a fallback,
* all of the usual Hystrix state and circuit-breaker state/metrics are updated to indicate the command failure.
*/
@Override
protected String getFallback() {
return "CircuitBreaker fallback: " + name;
}
public static class UnitTest {
@Test
public void testSynchronous() throws IOException {
for(int i = 0; i < 50000; i++) {
try {
System.out.println("===========" + new HystrixCircuitBreakerTest(String.valueOf(i), new MorningService()).execute());
// 查看熔断器是否打开
System.out.println("if circuit breaker open: " + HystrixCircuitBreaker.Factory.getInstance(HystrixCommandKey.Factory.asKey("CircuitBreakerTestKey")).isOpen());
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
来看执行结果:
1. 降级
超时的请求走fallback,熔断器还没有打开。
2. 熔断
熔断器打开了,后续请求直接走降级方法fallback,不再调用主流程方法。
3. 尝试恢复
过了熔断器工作的时间窗以后,尝试放一个请求进去,执行成功就关闭熔断器,失败则继续打开,如此往复循环进行工作。
熔断器模式,参考CircuitBreaker,
还有美团精华文章服务容错模式
最后,我想说熔断降级确实没毛病!哈哈!
解决问题的模式是相通的,关键还是要多思考
---------------------
作者:jiaobuchong
来源:CSDN
原文:https://blog.csdn.net/jiaobuchong/article/details/78232920
版权声明:本文为博主原创文章,转载请附上博文链接!