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


声明:本文转载自https://my.oschina.net/JavaLaw/blog/1572288,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

本文节选自《疯狂Spring Cloud微服务架构实战》

Spring Cloud教学视频:https://my.oschina.net/JavaLaw/blog/1552993

Spring Cloud电子书:https://my.oschina.net/JavaLaw/blog/1570383

18 断路器的开启和关闭

断路器开启

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

        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 MyCommand extends 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教学视频:https://my.oschina.net/JavaLaw/blog/1552993

Spring Cloud电子书:https://my.oschina.net/JavaLaw/blog/1570383

本书代码共享地址:https://gitee.com/yangenxiong/SpringCloud

本文发表于2017年11月12日 22:34
(c)注:本文转载自https://my.oschina.net/JavaLaw/blog/1572288,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2064 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1