本節詳細講解使用Hystrix的通用方式。git
Hystrix是由Netflix開源的一個延遲和容錯庫,用於隔離訪問遠程系統、服務或者第三方庫,防止級聯失敗,從而提高系統的可用性與容錯性。Hystrix主要經過如下幾點實現延遲和容錯。github
使用HystrixCommand(或HystrixObservableCommand)包裹對依賴的調用邏輯,每一個命令在獨立線程中執行。這使用到了設計模式中的「命令模式」。spring
當某服務的錯誤率超過必定閾值時,Hystrix能夠自動或者手動跳閘,中止請求該服務一段時間。設計模式
Hystrix爲每一個依賴都維護了一個小型的線程池(或者信號量)。若是該線程池已滿,發往該依賴的請求就被當即拒絕,而不是排隊等候,從而加速失敗斷定。併發
Hystrix能夠近乎實時地監控運行指標和配置的變化,例如成功、失敗、超時、以及被拒絕的請求等。app
當請求失敗、超時、被拒絕,或當斷路器打開時,執行回退邏輯。回退邏輯可由開發人員自行提供,例如返回一個缺省值。ide
斷路器打開一段時間後,會自動進入「半開」狀態。斷路器打開、關閉、半開的邏輯轉換,前面咱們已經詳細探討過了,再也不贅述。微服務
加依賴:高併發
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
加註解:在啓動類上添加@EnableCircuitBreaker
註解。測試
使用:
@HystrixCommand(fallbackMethod = "findByIdFallback") @GetMapping("/users/{id}") public User findById(@PathVariable Long id) { // 這裏用到了RestTemplate的佔位符能力 User user = this.restTemplate.getForObject( "http://microservice-provider-user/users/{id}", User.class, id ); // ...電影微服務的業務... return user; } public User findByIdFallback(Long id) { return new User(id, "默認用戶", "默認用戶", 0, new BigDecimal(1)); }
由代碼可知,只需使用@HystrixCommand
註解,就可保護該API。這裏的」保護「,其實帶有三層含義——」超時機制「、」倉壁模式「、」斷路器「!若是您不瞭解這些是什麼,或者想要探尋其中原理,可詳見:跟我學Spring Cloud(Finchley版)-12-微服務容錯三板斧
TIPS
本例使用了fallbackMethod
屬性,指定了一個降級方法,如不指定,Hystrix會有一個默認的降級方案,那就是拋異常,哈哈哈。
**如何知道斷路器打開仍是關閉呢?**還記得健康檢查嗎?只需訪問應用的/actuator/health
端點,便可查看!斷路器的狀態——固然,你必須添加以下配置:
management: endpoint: health: show-details: always
若是您對這部分知識有遺忘,可前往跟我學Spring Cloud(Finchley版)-03-監控:強大的Spring Boot Actuator 簡單複習一下。
啓動microservice-discovery-eureka
啓動microservice-provider-user
啓動microservice-consumer-movie-ribbon-hystrix-common
訪問http://localhost:8010/movies/users/1
,能正常返回結果
關閉microservice-provider-user
,再次訪問http://localhost:8010/movies/users/1
,可返回相似以下結果,說明當服務提供者時,服務消費者進入了回退方法。
{"id":1,"username":"默認用戶","name":"默認用戶","age":0,"balance":1}
訪問http://localhost:8010/actuator/health
,可得到相似以下結果:
{ "status": "UP", "details": { "diskSpace": ..., "refreshScope": ..., "discoveryComposite": ..., "hystrix": { "status": "UP" } } }
由結果不難發現,此時斷路器並未打開!這是爲何呢? 緣由是:此時只請求了一次,沒有達到Hystrix的閾值——Hystrix設計來保護高併發應用的,它要求10秒(可用hystrix.command.default.metrics.rollingStats.timeInMilliseconds
自定義)之內API錯誤次數超過20次(用circuitBreaker.requestVolumeThreshold
自定義),此時纔可能觸發斷路器。
持續不斷地訪問http://localhost:8010/movies/users/1
屢次(至少20次)
再次訪問http://localhost:8010/actuator/health
,可得到相似以下結果:
{ "status": "UP", "details": { "diskSpace": ..., "refreshScope": ..., "discoveryComposite": ..., "hystrix": { "status": "CIRCUIT_OPEN", "details": { "openCircuitBreakers": ["MovieController::findById"] } } } }
由結果可知,此時斷路器已經打開,而且列出了是哪一個API的斷路器被打開了。
在實際項目中,極可能須要得到形成fallback的緣由,此時可將代碼修改成以下:
@HystrixCommand(fallbackMethod = "findByIdFallback") @GetMapping("/users/{id}") public User findById(@PathVariable Long id) { // 這裏用到了RestTemplate的佔位符能力 User user = this.restTemplate.getForObject( "http://microservice-provider-user/users/{id}", User.class, id ); // ...電影微服務的業務... return user; } public User findByIdFallback(Long id, Throwable throwable) { log.error("進入回退方法", throwable); return new User(id, "默認用戶", "默認用戶", 0, new BigDecimal(1)); }
http://www.itmuch.com/spring-cloud/finchley-13/