您的位置:首页 > 编程语言 > Java开发

疯狂Spring Cloud连载(18)Hystrix断路器的开启和关闭

2017-11-11 22:12 731 查看
 本文节选自《疯狂Spring Cloud微服务架构实战》

京东购买地址::https://item.jd.com/12256011.html

当当网购买地址::http://product.dangdang.com/25201393.html
Spring Cloud教学视频:http://blog.csdn.net/boxiong86/article/details/78399104
Spring Cloud电子书:http://blog.csdn.net/boxiong86/article/details/78488226


18 Hystrix断路器的开启和关闭


断路器开启

断路器一旦开启,就会直接调用回退方法,不再执行命令,而且也不会更新链路的健康状况。断路器的开启要满足两个条件:

     1、整个链路达到一定的阀值,默认情况下,10秒内产生超过20次请求,则符合第一个条件。

     2、满足第一个条件的情况下,如果请求的错误百分比大于阀值,则会打开断路器,默认为50%。

Hystrix的逻辑,先判断是否满足第一个条件,再判断第二个条件,如果两个条件都满足,则会开启断路器。断路器开启的测试代码,请见代码清单6-8。

代码清单6-8:

codes\06\6.2\first-hnystrix-client\src\main\java\org\crazyit\cloud\breaker\OpenTest.java

public class OpenTest {

 

public static void main(String[] args) throws Exception {

// 10秒内有10个请求,则符合第一个条件

ConfigurationManager.getConfigInstance().setProperty(

"hystrix.command.default.metrics.rollingStats.timeInMilliseconds",
10000);


ConfigurationManager.getConfigInstance().setProperty(

"hystrix.command.default.circuitBreaker.requestVolumeThreshold",
10);


ConfigurationManager.getConfigInstance().setProperty(

"hystrix.command.default.circuitBreaker.errorThresholdPercentage",
50);


for(int i = 0; i <15;
i++) {

//执行的命令全部都会超时

MyCommand
c = new MyCommand();

c.execute();

//断路器打开后输出信息

if(c.isCircuitBreakerOpen())
{

System.out.println("断路器被打开,执行第"
+ (i + 1) + " 个命令");

}

}

}

 

/**

*模拟超时的命令

* @author杨恩雄

*

*/

static class MyCommandextends HystrixCommand<String> {

//设置超时的时间为500毫秒

public MyCommand() {

    super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))

            .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()

           .withExecutionTimeoutInMilliseconds(500))

   );

}

 

protected String run() throws Exception {

//模拟处理超时

Thread.sleep(800);

return
"";

}

 

@Override

protected String getFallback() {

return
"";

}

}

}

注意代码清单6-8中的三个配置,第一个配置了数据统计的时间,第二个配置了请求的阀值,第三个配置了错误百分比。如果在10秒内,有大于10个请求发生,并且请求的错误率超过50%,则开启断路器。

命令类MyCommand中,设置了命令执行的超时时间为500毫秒,命令执行需要800毫秒,换言之,该命令总会超时,命令模拟了现实环境中所依赖的服务瘫痪(超时响应)的情况。

在运行类中,循环15次执行命令,调用isCircuitBreakerOpen方法,如果断路器打开,则输出信息。运行代码清单6-8的OpenTest类,输出如下:

断路器被打开,执行第 11个命令

断路器被打开,执行第 12个命令

断路器被打开,执行第 13个命令

断路器被打开,执行第 14个命令

断路器被打开,执行第 15个命令

根据结果可知,前面执行的10个命令没有开启断路器,而到了第11个命令,断路器被打开,命令不再执行。


断路器关闭

断路器打开后,在一段时间内,命令不会再执行(一直触发回退),这段时间我们称作“休眠期”。休眠期默认值为5秒,休眠期结束后,Hystrix会尝试性的执行一次命令,此时断路器的状态不是开启,也不是关闭,而是一个半开的状态,如果这一次命令执行成功,则会关闭断路器并清空链路的健康信息,如果执行失败,断路器会继续保持打开的状态。断路器的打开与关闭测试,请见代码清单6-9。

代码清单6-9:

codes\06\6.2\first-hnystrix-client\src\main\java\org\crazyit\cloud\breaker\CloseTest.java

public class CloseTest {

 

public static void main(String[] args) throws Exception {

// 10秒内有3个请求就满足第一个开启断路器的条件

ConfigurationManager.getConfigInstance().setProperty(

"hystrix.command.default.metrics.rollingStats.timeInMilliseconds",
10000);

ConfigurationManager.getConfigInstance().setProperty(

"hystrix.command.default.circuitBreaker.requestVolumeThreshold",
3);

//请求的失败率,默认值为50%

ConfigurationManager.getConfigInstance().setProperty(

"hystrix.command.default.circuitBreaker.errorThresholdPercentage",
50);

//设置休眠期,断路器打开后,这段时间不会再执行命令,默认值为5秒,此处设置为3秒

ConfigurationManager.getConfigInstance().setProperty(

"hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds",
3000);


//该值决定是否执行超时

boolean isTimeout = true;

for(int i = 0; i < 10; i++) {

//执行的命令全部都会超时

MyCommand
c = new MyCommand(isTimeout);

c.execute();

//输出健康状态等信息

HealthCounts
hc = c.getMetrics().getHealthCounts();

System.out.println("断路器状态:"
+ c.isCircuitBreakerOpen() +

",请求总数:"
+ hc.getTotalRequests());

if(c.isCircuitBreakerOpen())
{

//断路器打开,让下一次循环成功执行命令

isTimeout
= false;


System.out.println("===== 断路器打开了,等待休眠期结束  =====");

//休眠期会在3秒后结束,此处等待4秒,确保休眠期结束

Thread.sleep(4000);

}

}

}

 

/**

*模拟超时的命令

* @author杨恩雄

*

*/

static class MyCommand extends HystrixCommand<String> {

private boolean isTimeout;

//设置超时的时间为500毫秒

public MyCommand(boolean isTimeout) {

    super(

   Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))

            .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()

           .withExecutionTimeoutInMilliseconds(500))

   );

    this.isTimeout = isTimeout;

}

 

protected String run() throws Exception {

//让外部决定是否超时

if(isTimeout)
{

//模拟处理超时

Thread.sleep(800);

}
else {

Thread.sleep(200);

}

return
"";

}

 

@Override

protected String getFallback() {

return
"";

}

}

}

代码清单中,配置了休眠期为3秒,循环10次,创建10个命令并予执行。在执行完第4个命令后,断路器会被打开,此时我们等待休眠期结束,让下次循环的命令执行成功。

代码清单中使用了一个布而值来决定是否执行成功,第5次命令会执行成功,此时断路器将会被关闭,剩下的命令全部都可以正常执行。在循环体中,使用了HealthCounts对象,该对象用于记录链路的健康信息,如果断路器关闭(链路恢复健康),HealthCounts里面的健康信息将会被重置。运行代码清单6-9,效果如下:

断路器状态:false,请求总数:0

断路器状态:false,请求总数:1

断路器状态:false,请求总数:2

断路器状态:true,请求总数:3

=====  断路器打开了,等待休眠期结束  =====

断路器状态:false,请求总数:0

断路器状态:false,请求总数:1

断路器状态:false,请求总数:1

断路器状态:false,请求总数:3

断路器状态:false,请求总数:3

断路器状态:false,请求总数:5

 本文节选自《疯狂Spring Cloud微服务架构实战》
Spring Cloud教学视频:http://blog.csdn.net/boxiong86/article/details/78399104
Spring Cloud电子书:http://blog.csdn.net/boxiong86/article/details/78488226
本书代码共享地址:https://gitee.com/yangenxiong/SpringCloud



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息