首先,介紹下問題:
一個plat-gateway工程,配置了Hystrix。按照通用的配置,如下驗證:
@RestController
public class SelfHystrixController {
@RequestMapping("/defaultfallback")
public Map<String,String> defaultfallback(){
log.info(LogMessage.getMessage("", "請求被熔斷了"));
Map<String,String> map = new HashMap<>();
map.put("msg","網絡繁忙服務降級請稍後再訪問");
map.put("code","GW0001");
return map;
}
/**
* 發起Get 請求 :localhost:8000/gateway/timeout
* 會進行熔斷
* @return
*/
@RequestMapping("/timeout")
public String timeout(){
try {
Thread.sleep(15000);
} catch (Exception e) {
e.printStackTrace();
}
return "Hello, I am timeout return. If normal, you can not find me.";
}
}
Yml配置如下:
cloud:
# Gateway routes config
gateway:
default-filters:
- name: Hystrix
args:
name: fallbackcmd
fallbackUri: forward:/defaultfallback
routes:
# 走 fsp 的路由
- id: wish.plat-gateway.fsp
uri: http://127.0.0.1:80
order: 2
#網關斷言匹配
predicates:
- Path=/gateway/**
filters:
# - StripPrefix=4
- FspAdapt
如上,在controller中驗證是沒有問題的。但是發現,在 FspAdaptGatewayFilterFactory 的過濾器中,是無法熔斷。
配置 10s熔斷, 在過濾器中休眠 15s,執行post請求。期望是:到10s後,主動熔斷,返回前端信息。but,現實情況是,到達10秒後,繼續執行,執行完後,才返回前端。此時信息是:
{
"timestamp": "2019-10-31T00:54:57.352+0000",
"path": "/gateway/04320/07/B70001/arrange/newBusiness/1233333",
"status": 504,
"error": "Gateway Timeout",
"message": "Response took longer than configured timeout"
}
本人想過很多方案,第一:修改spring-cloud-gateway-core中的TimeoutException,爲RuntimeException,這樣就可以終止繼續執行了。第二:自定義一個 HystrixGatewayFilterFactory 來實現該功能。但是思來想去,spring cloud hystrix不應該這樣。因爲根本未達到熔斷的目的,猜想是對使用不夠深入瞭解。
在這樣一篇文章中,Spring Cloud Hystrix設計原理。請認真閱覽,發現如下是跟我相關的描述:
如果run() 或者construct()方法 的真實執行時間超過了Command設置的超時時間閾值, 則當前則執行線程(或者是獨立的定時器線程)將會拋出TimeoutException。拋出超時異常TimeoutException,後,將執行步驟8的Fallback降級處理。即使run()或者construct()執行沒有被取消或中斷,最終能夠處理返回結果,但在降級處理邏輯中,將會拋棄run()或construct()方法的返回結果,而返回Fallback降級處理結果。
需要注意的是,Hystrix無法強制 將正在運行的線程停止掉--Hystrix能夠做的最好的方式就是在JVM中拋出一個InterruptedException。如果Hystrix包裝的工作不拋出中斷異常InterruptedException, 則在Hystrix線程池中的線程將會繼續執行,儘管調用的客戶端已經接收到了TimeoutException。這種方式會使Hystrix 的線程池處於飽和狀態。大部分的Java Http Client 開源庫並不會解析 InterruptedException。所以確認HTTP client 相關的連接和讀/寫相關的超時時間設置。
3.1 斷路器相關配置:
circuitBreaker.forceOpen 是否強制將斷路器設置成開啓狀態 false
心想,這不就是說的我這種情況嗎?於是覺得可以查閱http的超時或者circuitBreaker.forceOpen來試一下。
美好的事情,總會發生。增加如下配置,生效了:
#熔斷相關配置
hystrix:
command:
default:
circuitBreaker:
# 強制將斷路器設置成開啓狀態
forceOpen: true
此刻,整個世界都好了。等等,本以爲到此結束,萬萬沒想到。
接下來,配置 timeoutInMilliseconds: 10000 ,去掉過濾器中的休眠,打算正常測試下。結果:熔斷,熔斷,熔斷。是的,連正常功能都不好使了,嚇得我趕緊去掉了這個參數。仔細一想,這個參數是,強制熔斷。so,不能隨便亂用。
http請求的超時,未找到相關設置。
結論:可能與設計原理,不是很一致,因此通過配置可能無法實現。暫時擱置/自定義過濾器實現/考慮下其他方案,如Sentinel等。
不急,時間會說明一切。(未完,待續)