SpringCloud系列十五:使用Hystrix實現容錯


1. 回顧

  上文講解了容錯的重要性,以及容錯需要實現的功能。

  本文來講解使用Hystrix實現容錯。

2. Hystrix簡介

  Hystrix是Netflix開源的一個延遲和容錯庫,用於隔離訪問遠程系統、服務或第三方庫,防止級聯失敗,從而提高系統的可用性與容錯性。

  Hystrix主要通過以下幾點實現延遲和容錯:

  • 包裹請求:使用HystrixCommand(或HystrixObservableCommand)包裹對依賴的調用邏輯,每個命令在獨立線程中執行。

    這使用到了設計模式中的“命令模式”。

  • 跳閘機制:當某服務的錯誤率超過一定閾值時,Hystrix可以自動或者手動跳閘,停止請求該服務一段時間。
  • 資源隔離:Hystrix為每個依賴都維護了一個小型的線程池(或者信號量)。如果該線程池已滿,發往該依賴的請求就被立即拒絕,

    而不是排隊等候,從而加速失敗判定。

  • 監控:Hystrix可以近乎實時地監控運行指標和配置的變化,例如成功、失敗、超時、以及被拒絕的請求等。
  • 回退機制:當請求失敗、超時、被拒絕,或當斷路器打開時,執行回退邏輯。回退邏輯可由開發人員自行提供,例如返回一個缺省值。
  • 自我修復:斷路器打開一段時間后,會自動進入“半開”狀態。斷路器打開、關閉、半開的邏輯轉換,上文已經詳細探討過,不再贅述。

3. 通用方式整合Hystrix

  > 復制項目 microservice-consumer-movie-ribbon,將 ArtifactId 修改為 microservice-consumer-movie-ribbon-hystrix

  > 添加 hystrix 的依賴

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

  > 在啟動類上添加 @EnableCircuitBreaker 或 @EnableHystrix 注解,從而為項目啟用斷路器支持

package com.itmuch.cloud.microserviceconsumermovieribbonhystrix; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication @EnableDiscoveryClient @EnableHystrix public class MicroserviceConsumerMovieRibbonHystrixApplication { public static void main(String[] args) { SpringApplication.run(MicroserviceConsumerMovieRibbonHystrixApplication.class, args); } @Bean @LoadBalanced // 實現負載均衡
    public RestTemplate restTemplate() { return new RestTemplate(); } }

  > 修改 MovieController,讓其中的findById方法具備容錯能力。

package com.itmuch.cloud.microserviceconsumermovieribbonhystrix.controller; import com.itmuch.cloud.microserviceconsumermovieribbonhystrix.pojo.User; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class MovieController { private static final Logger LOGGER = LoggerFactory.getLogger(MovieController.class); @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancerClient loadBalancerClient; @HystrixCommand(fallbackMethod = "findByIdFallback") @GetMapping("/user/{id}") public User findById(@PathVariable Long id) { return this.restTemplate.getForObject("http://microservice-provider-user/" + id, User.class); } @GetMapping("/log-instance") public void logUserInstance() { ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user"); // 打印當前選擇的是哪個節點
        MovieController.LOGGER.info("{}:{}:{}", serviceInstance.getServiceId(), serviceInstance.getHost(), serviceInstance.getPort()); } public User findByIdFallback(Long id) { LOGGER.warn("請求異常,執行回退方式"); User user = new User(); user.setId(-1L); user.setName("默認用戶"); return user; } }

  > 啟動項目 microservice-discovery-eureka

  > 啟動項目 microservice-provider-user

  > 啟動項目 microservice-consumer-movie-ribbon-hystrix

  > 訪問 http://localhost:8010/user/1,獲得如下結果,說明可正常訪問

  > 停止項目 microservice-provider-user

  > 訪問 http://localhost:8010/user/1,獲得如下結果,說明當用戶微服務不可用時,進入了回退方法

  注意:當請求失敗、被拒絕、超時或者斷路器打開時,都會進入回退方法。但進入回退方法並不意味着斷路器已被打開。

4. Hystrix斷路器的狀態監控與深入理解

  還記得之前已經為項目引入了Spring Boot Actuator 的依賴,該依賴的作用就是監控應用程序的運行狀態。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

  斷路器的狀態也會暴露在Actuator提供的 /actuator/health 端口中,這樣就可以直觀地了解斷路器的狀態。

  但是之前使用的是 Actuator 的默認配置。在默認配置中,/actuator/health 端口只能查看系統的狀態,不能查看詳細信息,

  因此需要對 Actuator進行進一步配置。

  在 application.yml 中添加如下配置

management:
  endpoint:
    health:
      show-details: always

  > 啟動項目 microservice-discovery-eureka

  > 啟動項目 microservice-consumer-movie-ribbon-hystrix

  > 訪問 http://localhost:8010/user/1,結果如下,說明已執行了回退邏輯,返回了默認用戶。

  > 訪問 http://localhost:8010/actuator/health,結果如下,此時Hystrix的狀態依然是 UP,這是因為我們的失敗率還沒有達到閾值

    (默認是5秒返回20次失敗)

  > 持續快速的訪問 http://localhost:8010/user/1,然后訪問 http://localhost:8010/actuator/health,此時結果如下

 

  注意:由上面的測試可以發現——執行回退邏輯並不代表斷路器已經打開。請求失敗、超時、被拒絕以及斷路器打開時都會執行回退邏輯。

5. Hystrix線程隔離策略與傳播上下文

  先來閱讀一下Hystrix官方Wiki(https://github.com/Netflix/Hystrix/wiki/Configuration#execution.isolation.strategy

  執行

    以下屬性控制 HystrixCommand.run() 是如何運行的

  execution.isolation.strategy

    這個屬性決定了 HystrixCommand.run() 以哪種隔離策略去執行,下面兩種選擇中的一個:

    • THREAD(線程隔離):它將在單獨的線程上執行,並發請求受線程池中的線程數量的限制。
    • SEMAPHORE(信號量隔離):它將在調用線程上執行,開銷相對較小,並發請求收到信號量個數的限制。

  Thread or Semaphore

    默認並且推薦的設置是,運行 HystrixCommand 使用線程隔離(THREAD)HystrixObservableCommand 使用信號量隔離(SEMAPHORE)

    在線程中執行命令有一個除網絡超時以外的額外保護層。

    一般來說,只有當調用負載非常高時(每個實例每秒調用數百次)才需要對 HystrixCommand 使用信號量隔離,因為這種場景下

    使用單獨線程開銷太高,這通常只適用於非網絡調用。

  

 

  了解了Hystrix的隔離策略后,再來看一下 Spring Cloud 官方的文檔(http://cloud.spring.io/spring-cloud-static/Finchley.M8/single/spring-cloud.html#_propagating_the_security_context_or_using_spring_scopes

  如果你想傳播線程本地的上下文到 @HystrixCommand,默認聲明將不會工作,因為它會在線程池中執行命令(在超時的情況下)。

  你可以使用一些配置,讓 Hystrix 使用相同的線程,或者直接在注解中讓 Hystrix 使用不同的隔離策略。例如:

@HystrixCommand(fallbackMethod = "stubMyService", commandProperties = { @HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE") } ) ...

  這也適用於使用 @SessionScope 和 @RequestSession 的情況。你會知道什么時候需要這么做,因為會發生一個運行時異常,

  說它找不到作用域上下文(scoped context)。

  你還可以將 hystrix.shareSecurityContext 屬性設置為 true,這樣將會自動配置一個 Hystrix 並發策略插件的 hook,這個hook會

  將 SecurityContext 從主線程傳輸到 Hystrix 的命令。因為 Hystrix 不允許注冊多個 Hystrix 策略,所以可以聲明 HystrixConcurrencyStrategy

  為一個Spring bean來實現擴展。Spring Cloud會在Spring的上下文中查找你的實現,並將其包裝在自己的插件中。

 

 

  把Spring Cloud 和 Hystrix 的文檔對照閱讀,可以幫助理解相關概念。

  • Hystrix的隔離策略有THREAD和SEMAPHORE兩種,默認是THREAD。
  • 正常情況下,保持默認即可。
  • 如果發生找不到上下文的運行時異常,可考慮將隔離策略設置為SEMAPHORE。

6. 總結

  本文講解了Hystrix的整合,對Hystrix斷路器的理解及監控,還有Hystrix的隔離策略與傳播上下文等。

  下文將講解Feign使用Hystrix。敬請期待~~~

7. 參考

  周立 --- 《Spring Cloud與Docker微服務架構與實戰》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM