spring cloud: Hystrix(二):簡單使用@HystrixCommand的commandProperties配置@HistrixProperty隔離策略spring
某電子商務網站在一個黑色星期五發生過載.過多的併發請求,致使用戶支付的請求延遲好久沒有響應,在等待很長時間後最終失敗。支付失敗又致使用戶從新刷新頁面並再次嘗試支付,進一步增長了服務器的負載,最終整個系統都崩潰了。服務器
斷路器模式
一個遠程調用對應着一個線程/進程。若是響應太慢,這個線程/進程就得不到釋放。資源就會被耗盡,最終致使服務不可用。
斷路器能夠理解爲對容易致使錯誤的操做的代理。這種代理可以統計一段時間內調用失敗的次數,並決定是正常請求依賴的服務仍是直接返回。
斷路器能夠實現快速失敗,當它在一段時間內檢測到許多相似的錯誤(例如超時),就會在以後的一段時間內,強迫對該服務的調用快速失敗,即再也不請求所依賴的服務。這樣,應用程序就不須浪費CPU時間去等待長時間的超時。
斷路器也能夠自動診斷依賴的服務是否已經恢復正常。網絡
正常狀況下斷路器關閉,可正常請求依賴的服務。 當一段時間內,請求失敗率達到必定閾值,斷路器就會打開。此時,不會再去請求依賴的服務。 斷路器打開一段時間後,會自動進入‘半開’狀態。此時,斷路器可容許一個請求訪問依賴的服務。若是請求可以調用成功,則關閉斷路器;不然繼續保持打開狀態。
Hystrix線程隔離策略與傳播上下文
Hystrix的隔離策略兩種: 分別是線程隔離和信號量隔離。併發
THREAD(線程隔離):使用該方式,HystrixCommand將會在單獨的線程上執行,併發請求受線程池中線程數量的限制。
SEMAPHORE(信號量隔離):使用該方式,HystrixCommand將會在調用線程上執行,開銷相對較小,併發請求受到信號量個數的限制。
Hystrix中默認而且推薦使用線程隔離(THREAD),由於這種方式有一個除網絡超時之外的額外保護。
通常來講,只有當調用負載異常高時(例如每一個實例每秒調用數百次)才須要信號量隔離,由於這種場景下使用THREAD開銷會比較高。信號量隔離通常僅適用於非網絡調用的隔離。
可使用execution.isolation.strategy屬性指定隔離策略。
正常狀況下,默認爲線程隔離, 保持默認便可。
若是發生找不到上下文運行時異常,可考慮將隔離策略設置爲SEMAPHORE。app
Feign使用Hystrix
前面講的是使用註解@HystrixCommand的fallbackMethod屬性實現回退的。然而,Feign是以接口形式工做的,它沒有方法體。
spring-boot
q請看例文網站
@RestController public class MovieController { @Autowired private RestTemplate restTemplate; @GetMapping("/movie/{id}") @HystrixCommand(fallbackMethod = "notfindback", commandProperties=@HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE") ) public User findById(@PathVariable Long id) { //http://localhost:7900/simple/ return restTemplate.getForObject("http://spring-boot-user/simple/" + id, User.class); } public User notfindback(Long id) { User user = new User(); user.setId(0L); return user; } }
這一段代碼:spa
@GetMapping("/movie/{id}") @HystrixCommand(fallbackMethod = "notfindback", commandProperties=@HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE") ) public User findById(@PathVariable Long id) { //http://localhost:7900/simple/ return restTemplate.getForObject("http://spring-boot-user/simple/" + id, User.class); }
若是不加@HystrixCommand的commandProperties=@HystrixProperty註解配置,那麼:restTemplate.getForObject()請求是一個線程;@HystrixCommand()是一個隔離線程。線程
加上@HystrixCommand的commandProperties=@HystrixProperty註解配置後,將2個線程合併到一個線程裏。代理