Spring Cloud(Finchley版)-13-通用方式使用Hystrix

http://www.globalshopping.top

本節詳細講解使用Hystrix的通用方式。

簡介

Hystrix是由Netflix開源的一個延遲和容錯庫,用於隔離訪問遠程系統、服務或者第三方庫,防止級聯失敗,從而提升系統的可用性與容錯性。Hystrix主要通過以下幾點實現延遲和容錯。

  • 包裹請求

使用HystrixCommand(或HystrixObservableCommand)包裹對依賴的調用邏輯,每個命令在獨立線程中執行。這使用到了設計模式中的“命令模式”。

  • 跳閘機制

當某服務的錯誤率超過一定閾值時,Hystrix可以自動或者手動跳閘,停止請求該服務一段時間。

  • 資源隔離

Hystrix爲每個依賴都維護了一個小型的線程池(或者信號量)。如果該線程池已滿,發往該依賴的請求就被立即拒絕,而不是排隊等候,從而加速失敗判定。

  • 監控

Hystrix可以近乎實時地監控運行指標和配置的變化,例如成功、失敗、超時、以及被拒絕的請求等。

  • 回退機制

當請求失敗、超時、被拒絕,或當斷路器打開時,執行回退邏輯。回退邏輯可由開發人員自行提供,例如返回一個缺省值。

  • 自我修復

斷路器打開一段時間後,會自動進入“半開”狀態。斷路器打開、關閉、半開的邏輯轉換,前面我們已經詳細探討過了,不再贅述。

通用方式使用Hystrix

服務降級

  • 加依賴:

    1
    2
    3
    4
    
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
  • 加註解:在啓動類上添加@EnableCircuitBreaker 註解。

  • 使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    @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 端點,即可查看!斷路器的狀態——當然,你必須添加如下配置:

    1
    2
    3
    4
    
    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 ,可返回類似如下結果,說明當服務提供者時,服務消費者進入了回退方法

    1
    
    {"id":1,"username":"默認用戶","name":"默認用戶","age":0,"balance":1}
    
  • 訪問http://localhost:8010/actuator/health ,可獲得類似如下結果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    {
    	"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 ,可獲得類似如下結果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    {
    	"status": "UP",
    	"details": {
    		"diskSpace": ...,
    		"refreshScope": ...,
    		"discoveryComposite": ...,
    		"hystrix": {
    			"status": "CIRCUIT_OPEN",
    			"details": {
    				"openCircuitBreakers": ["MovieController::findById"]
    			}
    		}
    	}
    }
    

    由結果可知,此時斷路器已經打開,並且列出了是哪個API的斷路器被打開了。

獲得造成fallback的原因

在實際項目中,很可能需要獲得造成fallback的原因,此時可將代碼修改爲如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@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));
}

配套代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章