Spring-Cloud之Hystrix熔斷器-5

  一、在分佈式系統中,服務與服務之間的依賴錯綜複雜,一種不可避免的情況就是某些服務會出現故障,導致依賴於它們的其他服務出現遠程調度的線程阻塞 Hystrix是Netflix 公司開源的一個項目,它提供了熔斷器功能,能夠阻止分佈式系統中出現聯動故障 Hystrix 是通過隔離服務的訪問點阻止聯動故障的,並提供了故障的解決方案,從而提高了整個分佈式系統的彈性

  二、Hystrix的產生:

  在複雜的分佈式系統中,可能有幾十個服務相互依賴,這些服務由於某些原因,例如機房的不可靠性、網絡服務商的不可靠性,導致某個服務不可用。如果系統不隔離該不可用的服務,可能會導致整個系統不可用。

  對於依賴 30 個服務的應用程序,每個服務的正常運行時間爲 99.99% ,對於單個服務來說, 99.99% 的可用是非常完美的。有99.99^30 = 99.7% 的可正常運行時間和 0.3% 的不可用時間,那麼 10 億次請求中有 3000000次失敗,實際的情況可能比這更糟糕。

  如果不設計整個系統的韌性,即使所有依賴關係表現良好,單個服務只有 0.01% 的不可用,由於整個系統的服務相互依賴,最終對整個系統的影響是非常大的。

  

   在上圖中一個用戶需要請求A、H、I、P。如果中間I服務網絡延遲或者發生故障,即A、H、P不可用。在高併發的情況下,單個服務的延遲會導致整個請求都處於延遲狀態,可能在幾秒鐘就使整個服務處於線程負載飽和的狀態。

  某個服務的單個點的請求故障會導致用戶的請求處於阻塞狀態,最終的結果就是整個服務的線程資源消耗殆盡。由於服務的依賴性,會導致依賴於該故障服務的其他服務也處於線程阻塞狀態,最終導致這些服務的線程資源消耗殆盡 直到不可用,從而導致整個問服務系統都不可用,即雪崩效應。

  爲了防止雪崩效應,因而產生了熔斷器模型。 Hystrix 是在業界表現非常好的 個熔斷器模型實現的開源組件,它是 Spring Cloud 組件不可缺少的一部分。

  三、Hystrix的設計原則:

  1)防止單個服務的故障耗盡整個服務的 Servlet 容器(例如 Tomcat )的線程資源。

  2)快速失敗機制,如果某個服務出現了故障,則調用該服務的請求快速失敗,而不是線程等待。

  3)提供回退( fallback )方案,在請求發生故障時,提供設定好的回退方案。

  4)使用熔斷機制,防止故障擴散到其他服務。

  5)提供熔斷器的監控組件 Hystrix Dashboard ,可以實時監控熔斷器的狀態。

  四、Hystrix的工作機制:

  

 

 

   首先,當服務的某個 API 接口的失敗次數在一定時間內小於設定的閥值時,熔斷器處於關閉狀態,該 API 接口正常提供服務 。當該API 接口處理請求的失敗次數大於設定的閥值時, Hystrix 判定該 API 接口出現了故障,打開熔斷器,這時請求該 API 接口會執行快速失敗的邏輯(即 fall back 回退的邏輯),不執行業務邏輯,請求的線程不會處於阻塞狀態。處於打開狀態的熔斷器,一段時間後會處於半打開狀態,並將一定數量的請求執行正常邏輯。剩餘的請求會執行快速失敗,若執行正常邏輯的請求失敗了,則熔斷器繼續打開。若成功了 ,則將熔斷器關閉。這樣熔斷器就具有了自我修復的能力

  五、服務中對Hystrix的基本使用

  1)Ribbon中使用Hystrix熔斷器(我們基於前面的Spring-Cloud之Ribbon負載均衡-3代碼進行改造)。

  a、加入依賴

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

  b、加入註解(@EnableHystrix)開啓熔斷器功能

package com.cetc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
public class HystrixRibbonApplication {

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

  c、修改RibbonServiceImpl.class的實現,在getPort方法上面加入@HystrixCommand註解,這樣這個接口就有了熔斷器功能了,其中@HystrixCommand中的fallbackMethod爲執行快速失敗的方法。

package com.cetc.service.impl;

import com.cetc.service.IRibbonService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class RibbonServiceImpl implements IRibbonService {

    @Autowired
    private RestTemplate restTemplate;

    @Override
    @HystrixCommand(fallbackMethod = "error")
    public Integer getPort() {
        return restTemplate.getForObject("http://client/api/test/getPort", Integer.class);
    }

    public Integer error() {
        return 0;
    }
}

  d、測試。啓動Eureka-Server、Eureka-Client、Hystrix-Ribbon端口分別爲8670、8673、8677。

  

   正常訪問時:

  

  服務異常時:

  

  2)Feign中使用Hystrix(代碼基於前面的Spring-Cloud之Feign聲明式調用-4進行調整)

  a、因爲Feign中自帶了Hystrix功能,所以不需要重新加入依賴。

  b、在application.yaml中開啓Hystrix的配置:

feign:
  hystrix:
    enabled: true

  c、編寫TestHystrix服務錯誤的執行方式,繼承Feign接口

package com.cetc.feign.hystrix;

import com.cetc.feign.client.TestFeign;
import org.springframework.stereotype.Component;

@Component
public class TestHystrix implements TestFeign{

    @Override
    public Integer getPort() {
        return 0;
    }
}

  d、在@FeignClient中加入回調的class。

package com.cetc.feign.client;

import com.cetc.config.FeignConfiguration;
import com.cetc.feign.hystrix.TestHystrix;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;

@Component
@FeignClient(value = "client", configuration = {FeignConfiguration.class}, fallback = TestHystrix.class)
public interface TestFeign {

    @GetMapping("/api/test/getPort")
    Integer getPort();
}

  e、測試、啓動Eureka-Server、Eureka-Client、Hystrix-Feign端口分別爲8670、8673、8678。

  

   正常訪問:

  

  服務器異常:

  

  六、Hystrix Dashboard監控熔斷器的狀態。

  在微服務架構中 ,爲了保證服務實例的可用性,防止服務實例出現故障導致線程阻塞,而出現了熔斷器模型 烙斷器的狀況反映了 個程序的可用性和健壯性,它是一個重要指標。Hystrix Dashboard 是監控 Hystrix 的熔斷器狀況的 個組件,提供了數據監控和 友好的圖形化展示界面。

  1)Hystrix Dashboard和Ribbon結合使用(代碼基於上面的熔斷器代碼編寫)

  a、加入依賴

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

  說明:因爲是監控所以加入actuator。hystrix爲起步依賴這裏需要。

  b、加入註解@EnableHystrixDashboard

package com.cetc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
@EnableHystrixDashboard
public class DashboardRibbonApplication {

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

  c、加入相關配置到application.yaml,放開actuator的訪問

management:
  endpoints:
    web:
      exposure:
        include: ["*"]

  d、測試。服務包含Eureka-Server、Eureka-Client、Dashboard-Ribbon。端口分別爲8670、8673、8679

  

 

 

   測試接口:

  

  訪問:http://127.0.0.1:8679/hystrix

  

 

 

   按照提示在輸入框中對應鏈接:http://127.0.0.1:8679/actuator/hystrix.stream,點擊Monitor Stream。測試效果

  

  上面數字代表的意思如下:

  

   2)Hystrix Dashboard和Feign結合使用(代碼基於上面的熔斷器代碼編寫)

  a、加入依賴:

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

  說明:雖然Feign繼承了hystrix,但那不是起步依賴說以這裏還是需要hystrix的依賴

  b、加入註解:

package com.cetc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
@EnableHystrixDashboard
public class DashboardFeignApplication {

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

  說明:爲什麼還是需要加入@EnableHystrix的註解呢,在使用Dashboard的時候需要這個註解,不然會出現錯誤。

  c、修改application.yaml配置

feign:
  hystrix:
    enabled: true
management:
  endpoints:
    web:
      exposure:
        include: ["*"]

  d、測試。啓動服務有Eureka-Server、Eureka-Client、Dashboard-Feign。端口分別爲8670、8673、8680.

  

 

  測試正常的接口:

  

  訪問:http://127.0.0.1:8680/hystrix

  

  按提示輸入監控鏈接:http://127.0.0.1:8680/actuator/hystrix.stream,點擊Monitor Stream。效果如下:

  

   數字代表的意義:

  

   七、Turbine聚合監控。

  在使用 Hystrix Dashboard 組件監控服務的熔斷器狀況時, 每個服務都有一個HystrixDashboard 主頁,當服務數量很多時,監控非常不方便。爲了同時監控多個服務的熔斷器的狀況, Netflix 開源了 Hystrix 的另 個組件 Turbine Turbine 用於聚合多個 Hystrix Dashboard,將多個 Hystrix Dashboard 組件的數據放在一個頁面上展示,進行集中監控。

  1)加入依賴:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-turbine</artifactId>
        </dependency>

  2)修改配置application.yaml

server:
  port: 8681
eureka:
  client:
    service-url:
      defaultZone:
        http://127.0.0.1:8670/eureka/ # 實際開發中建議使用域名的方式
spring:
  application:
    name: turbine
turbine:
  aggregator:
    cluster-config: default
  app-config: dashboard-ribbon,dashboard-feign
  cluster-name-expression: new String("default")
management:
  endpoints:
    web:
      exposure:
        include: ["*"]

  說明:這裏的turbine配置主要是加入服務app-config,兩個服務均是之前寫好的服務。

  3)編寫啓動項加入註解:

package com.cetc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;

@SpringBootApplication
@EnableEurekaClient
@EnableHystrixDashboard
@EnableTurbine
public class TurbineApplication {

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

  4)測試。啓動服務有Eureka-Server、Eureka-Client、Dashboard-Ribbon、Dashboard-Feign、Turbine。端口分別爲8670、8673、8679、8680、8681.

  

   測試正常服務訪問:

  

  

  打開:http://127.0.0.1:8681/hystrix

  

 

   按照提示輸入:http://127.0.0.1:8681/turbine.stream。點擊Monitor Stream。效果如下

  

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