微服務SpringCloud之熔斷器

社會主義接班人發表於2019-07-14

   學習SpringCloud微服務是參考純潔的微笑部落格,看到他提到股市的熔斷我也忍不住吐槽一下,記得當時實施熔斷第一天就熔斷了,現在想想也還是搞笑,從之前的全民炒股到現在的全民炒房,都是一個炒字,問題是現在的房市和之前股市的5000點一樣,再加上貿易戰、人口老齡化等因素,不知道能撐多久,可能是一悲觀主義者,我是不太樂觀。

   熔斷和家裡的保險絲一樣,啟動保護作用,電壓過高或過低會導致電器損壞,保險絲的作用就是當電壓異常時直接斷掉,不至於影響其他電器的使用,而且保險絲也只是一根線,壞掉也影響不大,是預防雪崩的一種方法。Redis裡面有雪崩和穿透,SpringCloud中也有雪崩。A服務呼叫B服務、B服務呼叫C服務,C服務呼叫D服務,如果D服務掛了,那如果不做保護,C服務也會結束通話,C掛了B也會掛,B掛了A也掛,這樣就會都掛了,這就需要有一個壯士斷腕的勇氣,和習大大的理論是異曲同工之妙。一旦雪崩那恢復的順序正好相反,應該先恢復D服務,再依次恢復C、B、A。不然假如先恢復A,那B還是掛了的,到時候A還是會掛。下面是比較書面的介紹。

1.斷路器機制

斷路器很好理解, 當Hystrix Command請求後端服務失敗數量超過一定比例(預設50%), 斷路器會切換到開路狀態(Open). 這時所有請求會直接失敗而不會傳送到後端服務. 斷路器保持在開路狀態一段時間後(預設5秒), 自動切換到半開路狀態(HALF-OPEN). 這時會判斷下一次請求的返回情況, 如果請求成功, 斷路器切回閉路狀態(CLOSED), 否則重新切換到開路狀態(OPEN). Hystrix的斷路器就像我們家庭電路中的保險絲, 一旦後端服務不可用, 斷路器會直接切斷請求鏈, 避免傳送大量無效請求影響系統吞吐量, 並且斷路器有自我檢測並恢復的能力.

2.Fallback

Fallback相當於是降級操作. 對於查詢操作, 我們可以實現一個fallback方法, 當請求後端服務出現異常的時候, 可以使用fallback方法返回的值. fallback方法的返回值一般是設定的預設值或者來自快取.

3.資源隔離

在Hystrix中, 主要通過執行緒池來實現資源隔離. 通常在使用的時候我們會根據呼叫的遠端服務劃分出多個執行緒池. 例如呼叫產品服務的Command放入A執行緒池, 呼叫賬戶服務的Command放入B執行緒池. 這樣做的主要優點是執行環境被隔離開了. 這樣就算呼叫服務的程式碼存在bug或者由於其他原因導致自己所線上程池被耗盡時, 不會對系統的其他服務造成影響. 但是帶來的代價就是維護多個執行緒池會對系統帶來額外的效能開銷. 如果是對效能有嚴格要求而且確信自己呼叫服務的客戶端程式碼不會出問題的話, 可以使用Hystrix的訊號模式(Semaphores)來隔離資源.

在SpringCloud中實現也比較簡單,Feign中已經依賴了Hystrix所以在maven配置上不用做任何改動,只需要三步即可。

1.配置檔案

在上一部落格的EurekaConsumer基礎上,在屬性檔案中啟動fegin的Hystrix功能。

feign.hystrix.enabled=true

2.建立回撥類

package com.example.demo;

import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestParam;

@Component
public class HelloRemoteHystrix implements HelloRemote {
    @Override
    public String hello(@RequestParam(value = "name") String name) {
        return "hello " +name+", this messge send by Hystrix ";
    }
}

3.新增fallback屬性

在HelloRemote類新增指定fallback類,在服務熔斷的時候返回fallback類中的內容。

package com.example.demo;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name= "spring-cloud-producer",fallback = HelloRemoteHystrix.class)
public interface HelloRemote {

    @RequestMapping(value = "/hello")
    public String hello(@RequestParam(value = "name") String name);

}

此時已完成引入熔斷器,我們可以測試下。依次啟動服務EurekaServer、生產者EurekaClient、消費者EurekaConsumer。

此時輸入http://localhost:9001/hello?name=cuiyw時,輸出正常如下:

當EurekaClient停止時,再次輸入http://localhost:9001/hello?name=cuiyw,輸出如下,返回的是上面加的熔斷fallback類,說明熔斷成功。

 參考:http://www.ityouknow.com/springcloud/2017/05/16/springcloud-hystrix.html

相關文章