一文帶你們完全搞懂Hystrix!

前言?

  1. Netflix Hystrix斷路器是什麼?

Netflix Hystrix是SOA/微服務架構中提供服務隔離、熔斷、降級機制的工具/框架。Netflix Hystrix是斷路器的一種實現,用於高微服務架構的可用性,是防止服務出現雪崩的利器。java

  1. 爲何須要斷路器

在分佈式架構中,一個應用依賴多個服務是很是常見的,若是其中一個依賴因爲延遲太高發生阻塞,調用該依賴服務的線程就會阻塞,若是相關業務的QPS較高,就可能產生大量阻塞,從而致使該應用/服務因爲服務器資源被耗盡而拖垮。web

另外,故障也會在應用之間傳遞,若是故障服務的上游依賴較多,可能會引發服務的雪崩效應。就跟數據癱瘓,會引發依賴該數據庫的應用癱瘓是同樣的道理。spring

當一個應用依賴多個外部服務,一切都正常的狀況下,以下圖:數據庫

若是其中一個依賴發生延遲,當前請求就會被阻塞json

出現這種狀況後,若是沒有應對措施,後續的請求也會被持續阻塞緩存

每一個請求都佔用了系統的CPU、內存、網絡等資源,若是該應用的QPS較高,那麼該應用因此的服務資源會被快速消耗完畢,直至應用死掉。若是這個出問題的依賴(Dependency I),不止這一個應用,亦或是受影響的應用上層也有更多的依賴,那就會帶來咱們前面所提到的服務雪崩效應。 因此,爲了應對以上問題,就須要有支持服務隔離、熔斷等操做的工具。服務器

Hystrix 簡介

  1. Hystrix具有哪些能力/優勢?

    在經過網絡依賴服務出現高延遲或者失敗時,爲系統提供保護和控制 能夠進行快速失敗,縮短延遲等待時間和快速恢復:當異常的依賴回覆正常後,失敗的請求所佔用的線程會被快速清理,不須要額外等待 提供失敗回退(Fallback)和相對優雅的服務降級機制 提供有效的服務容錯監控、報警和運維控制手段網絡

  2. Hystrix 如何解決級聯故障/防止服務雪崩?

  • Hystrix將請求的邏輯進行封裝,相關邏輯會在獨立的線程中執行架構

  • Hystrix有自動超時策略,若是外部請求超過閾值,Hystrix會以超時來處理併發

  • Hystrix會爲每一個依賴維護一個線程池,當線程滿載,不會進行線程排隊,會直接終止操做

  • Hystrix有熔斷機制: 在依賴服務失效比例超過閾值時,手動或者自動地切斷服務一段時間 因此,當引入了Hystrix以後,當出現某個依賴高延遲的時候

Hystrix 工做原理

  1. Hystrix工做流

  1. 建立HystrixCommand 或者 HystrixObservableCommand 對象
  2. 執行命令execute()、queue()、observe()、toObservable()
  3. 若是請求結果緩存這個特性被啓用,而且緩存命中,則緩存的迴應會當即經過一個Observable對象的形式返回
  4. 檢查熔斷器狀態,肯定請求線路是不是開路,若是請求線路是開路,Hystrix將不會執行這個命令,而是直接執行getFallback
  5. 若是和當前須要執行的命令相關聯的線程池和請求隊列,Hystrix將不會執行這個命令,而是直接執行getFallback
  6. 執行HystrixCommand.run()或HystrixObservableCommand.construct(),若是這兩個方法執行超時或者執行失敗,則執行getFallback()
  7. Hystrix 會將請求成功,失敗,被拒絕或超時信息報告給熔斷器,熔斷器維護一些用於統計數據用的計數器。這些計數器產生的統計數據使得熔斷器在特定的時刻,能短路某個依賴服務的後續請求,直到恢復期結束,若恢復期結束根據統計數據熔斷器斷定線路仍然未恢復健康,熔斷器會再次關閉線路。
  8. 依賴隔離Hystrix採用艙壁隔離模式隔離相互之間的依賴關係,並限制對其中任何一個的併發訪問。

可能會有人有疑問,爲何不依賴於HTTP Client去作容錯保護(快速失敗、熔斷等),而是在訪問依賴以外經過線程&線程池隔離的方式作這個斷路器(Hystrix)`

主要是如下幾個方面:

  • 不一樣的依賴執行的頻率不一樣,須要分開來對待
  • 不一樣的依賴可能須要不一樣的Client的工具/協議來訪問,好比咱們可能用HTTP Client,可能用Thrift Client。
  • Client在執行的過程當中也可能會出現非網絡異常,這些都應該被隔離
  • Client的變化會引發斷路器的變化

SpringCloud:Ribbon + Hystrix應用

  1. 項目中引入Hystrix

修改pom.xml,引入Spring Cloud Netflix Hystrix

  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  </dependency>
  1. 配置Hystrix啓動類

修改啓動類Application.java,增長@EnableHystrix註解開啓Hystrix

@EnableHystrix
@EnableDiscoveryClient
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
  1. 斷路處理實現

修改TestService.java,增長斷路器功能

  • 在index方法上增長註解 @HystrixCommand並經過fallbackMethod參數指定斷路後執行的方法
  • 定義斷路處理方法,返回服務/操做斷路後的提示
@Service
public class TestService {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "indexError")
    public Object index() {
        return restTemplate.getForObject("http://testservice", String.class);
    }

    public Object plus(int numA, int numB) {
        String url = String.format("http://testservice/plus?numA=%s&numB=%s", numA, numB);
        return restTemplate.getForObject(url, String.class);
    }

    public Object indexError() {
        return "{\"code\": 999,\"message\": \"服務斷路\"}";
    }
}
  1. 斷路處理測試

啓動 Application 項目, 訪問:http://localhost:8604/ti ,將看到

{
  "code": 0,
  "message""hello",
  "content": null,
  "serviceName""testservice",
  "host""localhost:8602"
}

關閉testservice,而後再訪問 http://localhost:8604/ti ,將看到

{
  "code": 999,
  "message""服務斷路"
}

至此完成Ribbon+Hystrix的熔斷。

SpringCloud:Feign + Hystrix應用

  1. 開啓Hystrix 修改application.yml,開啓Hystrix
feign:
  hystrix:
    enabled: true
  1. 斷路處理實現

新建 TestServiceHystrix.java做爲TestService的斷路處理實現


@Component
public class TestServiceHystrix implements TestService {

    @Override
    public String indexService() {
        return "{\"code\": 999,\"message\": \"服務斷路\"}";
    }

    @Override
    public Result plusService(int numA, int numB) {
        Result result = new Result();
        result.setCode(999);
        result.setMessage("服務斷路");
        return new Result();
    }

    @Override
    public Result plusabService(Plus plus) {
        Result result = new Result();
        result.setCode(999);
        result.setMessage("服務斷路");
        return new Result();
    }

    @Override
    public Result plus2Service(Plus plus) {
        Result result = new Result();
        result.setCode(999);
        result.setMessage("服務斷路");
        return new Result();
    }
}
  1. 修改TestService,指定fallback類
@FeignClient(value = "testservice", fallback = TestServiceHystrix.class)
public interface TestService {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    String indexService();

    @RequestMapping(value = "/plus", method = RequestMethod.GET)
    Result plusService(@RequestParam(name = "numA") int numA, @RequestParam(name = "numB") int numB);

    @RequestMapping(value = "/plus", method = RequestMethod.POST, consumes = "application/json")
    Result plusabService(Plus plus);

    @RequestMapping(value = "/plus2", method = RequestMethod.POST)
    Result plus2Service(@RequestBody Plus plus);

}
  1. 啓動 feign Application 項目
  • 訪問:http://localhost:8605/ti ,將看到
{
  "code": 0,
  "message""hello",
  "content": null,
  "serviceName""testservice",
  "host""localhost:8602"
}
  • 關閉testservice,而後再訪問 http://localhost:8605/ti ,將看到
{
  "code": 999,
  "message""服務斷路"
}

至此完成Feign+Hystrix的熔斷。

結束

歡迎關注公衆號! 公衆號回覆:入羣 ,掃碼加入咱們交流羣! 掃碼關注公衆號獲取更多學習資料

相關文章
相關標籤/搜索