目录
降级(fallback)
MorningService
package hystrix.degrade;
/**
* @Package Name : ${PACKAG_NAME}
* @Author : 1766318593@qq.com
* @Creation Date : 2019年04月03日上午11:20
* @Function : todo
*/
public class MorningService {
/**
* 超时
*/
public void timeout() {
int j = 0;
while (true) {
j++;
}
}
public static void main(String[] args) {
}
}
HystrixFallbackTest.java
package hystrix.degrade;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;
import org.junit.Test;
import java.io.IOException;
/**
* @Package Name : ${PACKAG_NAME}
* @Author : 1766318593@qq.com
* @Creation Date : 2019年04月03日上午11:21
* @Function : todo
*/
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
降级就是在执行主流程时,主流程突然出现意外执行不下去了,那就执行另外一个方法让主流程看起来是正常的(这个方法通常就是降级方法,似乎有些牵强)。
熔断(circuit breaker)
保险丝:电路中正确安置保险丝,保险丝就会在电流异常升高到一定的高度和热度的时候,自身熔断切断电流,保护了电路安全运行。(来自百度百科)
熔断就跟保险丝一样,当一个服务请求并发特别大,服务器已经招架不住了,调用错误率飙升,当错误率达到一定阈值后,就将这个服务熔断了。熔断之后,后续的请求就不会再请求服务器了,以减缓服务器的压力。
来一个栗子吧:
HystrixCircuitBreakerTest.java
代码块
package hystrix.circuitbreak;
import com.netflix.hystrix.*;
import hystrix.degrade.MorningService;
import org.junit.Test;
import java.io.IOException;
/**
* @Package Name : ${PACKAG_NAME}
* @Author : 1766318593@qq.com
* @Creation Date : 2019年04月03日上午11:26
* @Function : todo
*/
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(200) // 熔断器工作时间,超过这个时间,先放一个请求进去,成功的话就关闭熔断,失败就再等一段时间
)
);
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 < 50; 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. 尝试恢复
过了熔断器工作的时间窗以后,尝试放一个请求进去,执行成功就关闭熔断器,失败则继续打开,如此往复循环进行工作。