瘋狂Spring Cloud連載(18)Hystrix斷路器的開啓和關閉

 本文節選自《瘋狂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-8OpenTest類,輸出如下:

斷路器被打開,執行第 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

發佈了66 篇原創文章 · 獲贊 10 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章