天天看點

八、Hystrix斷路器

一、概述

1.1、分布式系統面臨的問題

  複雜分布式體系結構中的應用程式有數十個依賴關系,每個依賴關系在某些時候将不可避免的失敗。

八、Hystrix斷路器

  服務雪崩:多個微服務之間調用的時候,假設微服務A調用微服務B和微服務C,微服務B和微服務C又調用其他的微服務,這就是所謂的“扇出”。如果扇出的鍊路上某個微服務的調用響應時間過長或者不可用,對微服務A的調用就會占用越來越多的系統資源,進而引起系統崩潰,所謂的“雪崩”。

  對于高流量的應用來說,單一的後端依賴可能會導緻所有伺服器上的所有資源都在幾秒鐘内飽和,比失敗更糟糕的是,這些應用程式還可能導緻服務之間的延遲增加,備份隊列,線程和其他系統資源緊張,導緻整個系統發生更多的級聯故障。這些都表示需要對故障和延遲進行隔離和管理,以便單個依賴關系的失敗,不能取消整個應用程式或系統。

  通常當你發現一個子產品下的某一個執行個體失敗後,這時候這個子產品依然還會接收流量,然後這個有問題的子產品還調用了其他子產品,這樣就會發生級聯故障,或者雪崩。

1.2、Hystrix簡介

  Hystrix是一個用于處理分布式系統的延遲和容錯的開源庫,在分布式系統裡,許多依賴不可避免的會調用失敗,比如逾時、異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導緻整體服務失敗避免級聯故障,以提高分布式系統的彈性。

  “斷路器”本身是一種開關裝置,當某個服務單元發生故障後,通過斷路器的故障監控,向調用方傳回一個符合預期的、可處理的備選響應(FallBack),而不是長時間的等待或者抛出調用方無法處理的異常,這樣就保證了服務調用方的線程不會被長時間、不必要的占用,進而避免了故障在分布式系統中的蔓延、乃至雪崩。

  Hystrix一般用在服務消費端做服務降級。

1.3、功能作用

  • 服務降級
  • 服務熔斷
  • 接近實時的監控

二、Hystrix重要概念

2.1、服務降級(fallback)

  “伺服器忙,請稍候再試”,不讓用戶端等待并立刻傳回一個友好提示,fallback

  哪些情況會觸發降級:程式運作異常、逾時、服務熔斷觸發服務降級、線程池/信号量打滿也會導緻服務降級

2.2、服務熔斷break

  類比保險絲達到最大服務通路後,直接==拒絕通路==,拉閘限電,然後調用服務降級的方法并傳回友好提示

  服務的降級->進而熔斷->恢複調用鍊路

2.3、服務限流flowlimit

  秒殺高并發等操作,嚴禁一窩蜂的過來擁擠,大家排隊,一秒鐘N個,有序進行

三、hystrix案例

3.1、服務提供者

  • 建立Spring Boot 的Module名稱:cloud-provider-hystrix-payment8001
  • pom.xml添加如下依賴
<dependencies><!--hystrix--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency><!--eureka client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>      
  • 編寫application.yml
server:
  port: 8001eureka:
  client:
    register-with-eureka: true    #表識不向注冊中心注冊自己fetch-registry: true   #表示自己就是注冊中心,職責是維護服務執行個體,并不需要去檢索服務service-url:  defaultZone: http://eureka7001.com:7001/eureka/spring:
  application:
    name: cloud-provider-hystrix-payment      
  • 主啟動類加@EnableEurekaClient注解
@SpringBootApplication
@EnableEurekaClientpublic class PaymentHystrixMain8001 {public static void main(String[] args) {
        SpringApplication.run(PaymentHystrixMain8001.class,args);
    }
}      
  • 業務類
@Servicepublic class PaymentService {//成功public String paymentInfo_OK(Integer id) {return "線程池:" + Thread.currentThread().getName() + "   paymentInfo_OK,id:  " + id + "\t" + "哈哈哈";
    }//失敗public String paymentInfo_TimeOut(Integer id) {int timeNumber = 3;try {
            TimeUnit.SECONDS.sleep(timeNumber);
        } catch (Exception e) {
            e.printStackTrace();
        }return "線程池:" + Thread.currentThread().getName() + "   paymentInfo_TimeOut,id:  " + id + "\t" + "嗚嗚嗚" + " 耗時(秒)" + timeNumber;
    }

}      
@RestController
@Slf4jpublic class PaymentController {

    @Resourceprivate PaymentService paymentService;

    @Value("${server.port}")private String serverPort;

    @GetMapping("/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id){
        String result = paymentService.paymentInfo_OK(id);
        log.info("*******result:"+result);return result;
    }
    @GetMapping("/payment/hystrix/timeout/{id}")public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
        String result = paymentService.paymentInfo_TimeOut(id);
        log.info("*******result:"+result);return result;
    }
}      
  • 測試

1、正常測試

  • 啟動eureka7001
  • 啟動cloud-provider-hystrix-payment8001
  • 通路
    • 通路http://localhost:8001/payment/hystrix/ok/31
    • 每次調用耗費5秒鐘http://localhost:8001/payment/hystrix/timeout/31
  • 上述module均OK 。以上述為根基平台,從正确->錯誤->降級熔斷->恢複

2、高并發測試

  Jmeter壓測測試:參考部落格

  安裝:https://blog.csdn.net/weixin_41077341/article/details/110167555

  使用:https://www.cnblogs.com/stulzq/p/8971531.html

  開啟Jmeter,來20000個并發壓死cloud-provider-hystrix-payment8001,20000個請求都去通路paymentInfo_TimeOut服務

  • 再來一個通路
    • http://localhost:8001/payment/hystrix/ok/31
    • http://localhost:8001/payment/hystrix/timeout/31
  • 結果
    • 兩個都在自己轉圈圈
    • 為什麼會被卡死:tomcat的預設的工作線程數被打滿了,沒有多餘的線程來分解壓力和處理。

3.2、服務消費者

  • 建立Spring Boot Model名稱:cloud-consumer-feign-hystrix-order80
  • pom添加如下依賴
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</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-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>      
  • 編寫配置檔案application.yml
server
  port: 80eureka:
  client:
    register-with-eureka: true    #表識不向注冊中心注冊自己fetch-registry: true   #表示自己就是注冊中心,職責是維護服務執行個體,并不需要去檢索服務service-url:
             defaultZone: http://eureka7001.com:7001/eureka/spring:
  application:
    name: cloud-provider-hystrix-order      
  • 主啟動
@SpringBootApplication
@EnableFeignClients
public class OrderHystrixMain80 {
    public static void main(String[] args) {
      SpringApplication.run(OrderHystrixMain80.class,args);
    }
}      
@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")public interface PaymentHystrixService {
    @GetMapping("/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id);

    @GetMapping("/payment/hystrix/timeout/{id}")public String paymentInfo_TimeOut(@PathVariable("id") Integer id);
}      
@RestController
@Slf4jpublic class OrderHystrixController {

    @Resourceprivate PaymentHystrixService paymentHystrixService;

    @Value("${server.port}")private String serverPort;

    @GetMapping("/consumer/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id){
        String result = paymentHystrixService.paymentInfo_OK(id);
        log.info("*******result:"+result);return result;
    }
    @GetMapping("/consumer/payment/hystrix/timeout/{id}")public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
        String result = paymentHystrixService.paymentInfo_TimeOut(id);
        log.info("*******result:"+result);return result;
    }

}      

  http://localhost/consumer/payment/hystrix/ok/31

  2W個線程壓8001;消費端80微服務再去通路正常的OK微服務8001位址;http://localhost/consumer/payment/hystrix/timeout/31

  消費者80;要麼轉圈圈等待; 要麼消費端報逾時錯誤

3.3、故障現象和導緻原因 

  • 8001同一層次的其他接口服務被困死,因為tomcat線程裡面的工作線程已經被擠占完畢
  • 80此時調用8001,用戶端通路響應緩慢,轉圈圈
  • 正因為有上述故障或不佳表現,才有我們的降級/容錯/限流等技術誕生

3.4、如何解決?解決的要求

  解決思路

    • 逾時導緻伺服器變慢(轉圈)------逾時不再等待
    • 出錯(當機或程式運作出錯)------出錯要有兜底

  解決方案

    • 服務提供者(8001)逾時了,調用者(80)不能一直卡死等待,必須有服務降級
    • 服務提供者(8001)down機了,調用者(80)不能一直卡死等待,必須有服務降級
    • 服務提供者(8001)OK,調用者(80)自己出故障或有自我要求(自己的等待時間小于服務提供者),自己處理降級

四、服務降級

  降級配置: @HystrixCommand

4.1、在服務提供方做降級處理

  8001先從自身找問題;設定自身調用逾時時間的峰值,峰值内可以正常運作,超過了需要有兜底的方法處理,作服務降級fallback

/** * fallbackMethod = "paymentInfo_TimeOutHandler"  降級方法
     * @param id
     * @return */@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
        @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")
    })public String paymentInfo_TimeOut(Integer id) {try { TimeUnit.MILLISECONDS.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }return "線程池:  "+Thread.currentThread().getName()+" id:  "+id+"\t"+"O(∩_∩)O哈哈~"+"  耗時3(秒): ";
    }/** * 服務降級  的兜底方案
     * @param id
     * @return */public String paymentInfo_TimeOutHandler(Integer id) {return "線程池:  "+Thread.currentThread().getName()+" paymentInfo_TimeOutHandler,id:  "+id+"\t"+"(●ˇ∀ˇ●)";
    }      
  • 業務類啟用
    • @HystrixCommand報異常後如何處理
    • 一旦調用服務方法失敗并抛出了錯誤資訊後,會自動調用@HystrixCommand标注好的fallbackMethod調用類中的指定方法
  • 主啟動類激活
    • 添加新注解@EnableCircuitBreaker到主啟動類

4.2、在服務消費方做服務降級

  一般服務降級都是在服務調用方

  80訂單微服務,也可以更好的保護自己,微服務用戶端降級保護。

①、特定fallback

  每一個方法都對應着自己的fallback。

  • application.yml添加如下配置:
feign:
  hystrix:
    enabled: true #如果處理自身的容錯就開啟。開啟方式與生産端不一樣。      
  • 主啟動添加注解 @EnableHystrix
@RestController
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")public class OrderController { 
    
     @Resourceprivate PaymentHystrixService paymentHystrixService;    //調用服務提供方最多等待1.5秒@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
    })
    @GetMapping("/consumer/hystrix/timeout/{id}")public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
        String result = paymentHystrixService.paymentInfo_TimeOut(id);return result;
    }
public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {return "我是消費者80,對方支付系統繁忙請10秒鐘後再試或者自己運作出錯請檢查自己,o(╥﹏╥o";
    }
}      

  目前問題:每個業務方法都對應一個兜底的方法,引起代碼膨脹。

②、預設fallback

  解決代碼膨脹問題:配置預設fallback;每個方法配置一個fallback引起代碼膨脹;通過@DefaultProperties(defaultFallback)配置預設fallback

@RestController
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")public class OrderController {
    @Resourceprivate PaymentHystrixService paymentHystrixService;//調用服務提供方最多等待1.5秒    @HystrixCommand
    @GetMapping("/consumer/hystrix/timeout/{id}")public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
        String result = paymentHystrixService.paymentInfo_TimeOut(id);return result;
    }public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {return "我是消費者80,對方支付系統繁忙請10秒鐘後再試或者自己運作出錯請檢查自己,o(╥﹏╥)o";
    }// 下面是全局fallback方法public String payment_Global_FallbackMethod() {return "Global異常處理資訊,請稍後再試,/(ㄒoㄒ)/~~";
    }
}      

  目前問題

  • 兜底方法和業務邏輯混一起。我們的業務類PaymentController,目前fallback和業務類混合在一起。這樣每一個業務類都需要提供一個兜底方法。
  • 服務降級,用戶端去調用服務端,碰上服務端當機或關閉。本次案例服務降級處理是在用戶端80實作完成的,與服務端8001沒有關系,隻需要為Feign用戶端定義的接口添加一個服務降級處理的實作類即可實作解耦。

③、全局fallback

  修改cloud-consumer-feign-hystrix-order80。根據cloud-consumer-feign-hystrix-order80已經有的PaymentHystrixService接口,重新建立一個類(PaymentFallbackService)實作該接口,統一為接口裡面的方法進行異常處理

  • PaymentFallbackService類實作PaymentFeignClientService接口
@Componentpublic class PaymentFallbackService implements PaymentHystrixService {
    @Overridepublic String paymentInfo_OK(Integer id) {      return "-----PaymentFallbackService fall back-paymentInfo_OK , (┬_┬)";
    }

    @Override  public String paymentInfo_TimeOut(Integer id) {return "-----PaymentFallbackService fall back-paymentInfo_TimeOut , (┬_┬)";
  }
}      

  它的運作邏輯是:當請求過來,首先還是通過Feign遠端調用pay子產品對應的方法。但是如果pay子產品報錯,調用失敗,那麼就會調用PayMentFalbackService類的目前同名的方法,作為降級方法。

feign:
  hystrix:
  enabled: true #如果處理自身的容錯就開啟。開啟方式與生産端不一樣。      
  • PaymentFeignClientService接口
@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class)
public interface PaymentHystrixService {

    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id);

    @GetMapping("/payment/hystrix/timeout/{id}")
  public String paymentInfo_TimeOut(@PathVariable("id") Integer id);
}      
  • 單個eureka先啟動7001;PaymentHystrixMain8001啟動
  • 正常通路測試
    • http://localhost/consumer/payment/hystrix/ok/31
    • 故意關閉微服務8001
    • 用戶端自己調用提升:此時服務端provider已經down了,但是我們做了服務降級處理,讓用戶端在服務端不可用時也會獲得提示資訊而不會挂起耗死伺服器

五、服務熔斷

5.1、熔斷機制概述

  熔斷機制是應對雪崩效應的一種微服務鍊路保護機制,當扇對外連結路的某個微服務出錯不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的調用,快速傳回錯誤的相應資訊。

  當檢測到該節點微服務調用響應正常後,恢複調用鍊路。

  在Spring Cloud架構裡,熔斷機制通過Hystrix實作。Hystrix會監控微服務間調用狀況。當失敗的調用到一定的門檻值,預設是5秒内20次調用失敗,就會啟動熔斷機制,熔斷機制的注解是@HystrixCommand。

5.2、案例

@RestController
@Slf4j
public class PaymentController {

    @Autowired
    private PaymentService paymentService;//服務熔斷
    @GetMapping("/payment/circuit/{id}")
    public String paymentCircuitBreaker(@PathVariable("id") Integer id)
    {
        String result = paymentService.paymentCircuitBreaker(id);
        System.out.println("****result: "+result);return result;
    }
}      
@Servicepublic class PaymentService {/** * 傳入id >0 正确時列印“調用成功,流水号”
     * 傳入id <0 正确時抛出異常
     *
     *10秒中内請求的60%失敗,則服務熔斷走熔斷方法 paymentCircuitBreaker_fallback     *///=====服務熔斷     10秒中之内10次通路 失敗率超過60% 則觸發熔斷@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否開啟斷路器@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 請求次數@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 時間視窗期@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),// 失敗率達到多少後跳閘    })public String paymentCircuitBreaker(@PathVariable("id") Integer id) {if(id < 0) {throw new RuntimeException("******id 不能負數");
        }
        String serialNumber = IdUtil.simpleUUID();return Thread.currentThread().getName()+"\t"+"調用成功,流水号: " + serialNumber;
    }//熔斷後的降級方法public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) {return "id 不能負數,請稍後再試,/(ㄒoㄒ)/~~   id: " +id;
    }
}      

 測試

  • 多次通路:http://localhost:8001/payment/circuit/-1觸發熔斷。
  • 通路:http://localhost:8001/payment/circuit/1此時調用的fallback邏輯。
  • 但是,當過了幾秒後,又恢複了。因為在10秒視窗期内,它自己會嘗試接收部分請求,發現服務可以正常調用,慢慢的當錯誤率低于60%,取消熔斷

5.3、服務熔斷總結

1、涉及到斷路器的三個重要參數:

  • 快照時間窗:斷路器确定是否打開需要統計一些請求和錯誤資料,而統計的時間範圍就是快照時間窗,預設是10秒。
  • 請求總數門檻值:在快照時間窗内,必須滿足請求總數門檻值才有資格熔斷。預設是20秒,意味着在10秒内,如果該Hystrix指令的調用次數不超過20次,即使所有的請求都逾時或其他原因失敗,斷路器都不會打開。
  • 錯誤百分比門檻值:當請求總數在快照時間視窗内超過了門檻值,比如發生30次調用,如果在這30次調用中,有15次放生了逾時異常,也就是超國50%的錯誤百分比,在預設設定50%門檻值情況下,這時候會将斷路器打開。

2、熔斷類型:

  • 熔斷打開:請求不在進行調用目前服務,内部設定時鐘一般為MTR(平均故障時間),當熔斷打開時長達到所設時鐘則進入半熔斷狀态。
  • 熔斷關閉:熔斷關閉不會對服務進行熔斷。
  • 熔斷半開:部分請求根據規則調用目前服務,如果請求成功且符合規則,則認為目前服務恢複正常,關閉熔斷。

3、當斷路器開啟後

  1. 再有請求調用的時候,将不會調用主邏輯,而是直接調用降級fallback.通過斷路器,實作了自動地發現錯誤并将降級邏輯切換為主邏輯,減少響應延遲效果。
  2. 原來的主邏輯如何恢複 Hystrix實作了自動恢複功能。當斷路器打開,對主邏輯進行熔斷後,Hystrix會開啟一個休眠時間窗,在這個時間窗内,降級邏輯是臨時的成為主邏輯,當休眠的時間窗到期,斷路器将進入半開狀态,釋放一次請求到原來的主邏輯上,如果此次請求正常傳回,那麼斷路器将繼續閉合,斷路器關閉,主邏輯恢複,如果這次請求依然有問題,斷路器繼續進入打開狀态,休眠時間窗重新計時。

六、hystrix工作流程

  1. 建立HystrixCommand(用在依賴的服務傳回單個操作結果的時候)或者HystrixObserableCommand(用在依賴的服務傳回多個操作結果的時候)對象。
  2. 指令執行,其中HystrixCommand實作了下面兩種執行方式;而HystrixObserableCommand實作後面兩種執行方式
  • execute():同步執行,從依賴的服務傳回一個單一的結果對象,或是在發生錯誤的時候抛出異常。
  • queue():異步執行,直接傳回一個Future對象,其中包含了服務執行結結束時要傳回的單一結果對象。
  • Observe():傳回Observable對象,他代表了操作的多個結果,它是一個Hot Obserable(不論“事件源”是否有“訂閱者”,都會在建立後對事件進行釋出,是以對于Hot Obserable的每一個訂閱者都有可能是從“事件源”的中途開始的,并可能隻是看到了整個操作的局部過程)
  • toObservable():同樣會傳回Observable對象,也代表了操作的多個結果,但它傳回的是一個Cold Observable(沒有定于這的時候并不會釋出事件,而是進行等待,直到有訂閱者之後才釋出事件,是以對于Cold Observable的訂閱者,它可以保證從一開始看到整個操作的全部過程)

若目前指令的請求緩存功能是被啟用的,并且該指令緩存命中,那麼緩存的結果會立即以Observable對象的形式傳回。檢查斷路器是否為打開狀态。如果斷路器是打開的,那麼Hystrix不會執行指令,而是轉接到fallback處理邏輯(step 8);如果斷路器是關閉的,檢查是否有可用資源來執行指令(step 5)線程池/請求隊列/信号量是否占滿,如果指令依賴服務的專有線程池和請求隊列,或者信号量(不使用目前線程的時候)已經占滿,那麼Hystrix也不會執行指令,而是轉接到fallback處理邏輯(step 8)Hystrix會根據我們編寫的方法來決定采取什麼樣的方式去請求依賴服務,  Hystrix.run():傳回一個單一的結果,或者抛出異常。  HystrixObservableCommand.construct():傳回一個Observable對象來發射多個結果,或通過onError發送錯誤通知。Hystrix會将“成功”、“失敗”、“拒絕”、“逾時”等資訊報告給斷路器,而斷路器會維護一組電腦來統計這些資料。斷路器會使用這些統計資料來決定是否将斷路器打開,來對某個依賴服務的請求進行“熔斷/斷路”當指令執行失敗的時候,Hystrix會進入fallabck嘗試回退處理,我們通常也稱該操作為“服務降級”。而能夠引起服務降級處理的情況有下面幾種  step4:目前指令處于“熔斷/斷路”狀态,斷路器是打開的時候。  step5:目前指令是線程池、請求隊列或者信号量被占滿的時候。  step6:Hystrix.run()或者HystrixObservableCommand.construct()抛出異常的時候。當Hystrix指令執行成功之後,他會将處理結果直接傳回或是以Observable形式傳回。

  注意:我們沒有為指令實作降級邏輯或者在降級處理邏輯中抛出異常,Hystrix依然會傳回一個Observable對象,但是他不會發射任何結果資料,而是通過onError方法通知指令立即中斷請求,并通過onError()方法将引起指令失敗的異常發送給調用者。

七、服務監控hystrixDashboard

7.1、概述

  除了隔離依賴服務的調用以外,Hystrix還提供了準實時的調用監控(Hystrix Dashboard),Hystrix會持續地記錄所有通過Hystrix發起的請求的執行資訊,并以統計報表和圖形的形式展示給使用者,包括每秒執行多少請求,多少成功,多少失敗等,Netflix通過hystrix-metrics-event-stream項目實作了對以上名額的監控,Spring Cloud也提供了Hystrix Dashboard的整合,對監控内容轉化成可視化界面。

7.2、案例

  • 建立Spring Boot Model名稱:cloud-consumer-hystrix-dashboard9001
<dependencies><!--SpringCloud ailibaba nacos --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- SpringBoot整合Web元件 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--日常通用jar包配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>      
  • 編寫applicatin.yml
server:
  port: 9001      
  • HystrixDashboardMain9001+新注解@EnableHystrixDashboard
@SpringBootApplication
@EnableHystrixDashboardpublic class HystrixDashboardMain9001 {public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardMain9001.class,args);
    }
}      
  • 啟動cloud-consumer-hystrix-dashboard9001該微服務後續将監控微服務8001; http://localhost:9001/hystrix

7.3、斷路器示範

  修改cloud-provider-hystrix-payment8001;注意:新版本Hystrix需要在主啟動類MainAppHystrix8001中指定監控路徑。否則報Unable to connect to Command Metric Stream、404

@Beanpublic ServletRegistrationBean getServlet(){
    HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
    registrationBean.setLoadOnStartup(1);
    registrationBean.addUrlMappings("/hystrix.stream");
    registrationBean.setName("HystrixMetricsStreamServlet");return registrationBean;
}      

  監控測試

    • 啟動1個eureka或者3個eureka叢集均可
    • 觀察監控視窗:9001監控8001;http://localhost:8001/hystrix.stream
八、Hystrix斷路器

繼續閱讀