springcloud入門系列(6)-Hystrix詳解

本篇會(huì)介紹下Hystrix的使用,會(huì)從最簡單的入門實(shí)例開始,然后會(huì)講述下Hystrix的隔離和熔斷的原理和流程,最后講解下Hystrix的各類參數(shù)來指導(dǎo)大家更快上手。

1. Hystrix實(shí)例

1)Pom增加依賴

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

2)Application添加注解

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

3)controller增加HystrixCommand注解

Hystrix支持兩種方式定義HystrixCommand,一種是將類繼承自HystrixCommand類,重寫run方法,另一種是在方法頭上寫注解的方式,使用注解的方式代碼會(huì)比較清晰,將Hystrix代碼和業(yè)務(wù)代碼隔離開,具體屬性含義在接下來的章節(jié)會(huì)詳細(xì)介紹。

@RestController
public class TestController {
    @HystrixCommand(fallbackMethod = "error", commandProperties = {
            @HystrixProperty(name="execution.isolation.strategy", value = "THREAD"),
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "4000"),
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "40")
    }, threadPoolProperties = {
            @HystrixProperty(name = "coreSize", value = "1"),
            @HystrixProperty(name = "maxQueueSize", value = "10"),
            @HystrixProperty(name = "keepAliveTimeMinutes", value = "1000"),
            @HystrixProperty(name = "queueSizeRejectionThreshold", value = "8"),
            @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "12"),
            @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1440")
    })
    @RequestMapping(value = "/hello", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})
    public String hello(){
        return "hello hystrix!";
    }

    public String error() {
        return "hello error!";
    }

}

4)Hystrix Dashboard

Hystrix自帶了DashBoard,如果監(jiān)控單個(gè)實(shí)例,可以很方便的通過Hystrix的dashboard進(jìn)行查看運(yùn)行情況。

當(dāng)應(yīng)用運(yùn)行起來以后可以通過輸入http://localhost:8081/hystrix,如果看到小熊頁面表示進(jìn)入dashboard頁面。

Screenshot 2017-09-21 14.32.59.png

在輸入欄中輸入:http://localhost:8081/hystrix.stream可以查看這個(gè)階段的實(shí)時(shí)運(yùn)行情況。

Screenshot 2017-09-21 14.33.30.png

可以看到界面上按照service和接口都分別展示出來,如果有多個(gè)接口也會(huì)依次列開請(qǐng)求監(jiān)控情況。


Screenshot 2017-09-21 14.33.54.png

實(shí)例源碼下載:https://github.com/feiweiwei/springcloud-sample

2. Hystrxi熔斷隔離流程

Hystrix隔離的核心思想就是按照接口進(jìn)行線程池隔離,在沒有接觸Hystrix之前,我們也考慮過使用線程池做隔離,來實(shí)現(xiàn)隔離的功能,但是當(dāng)時(shí)考慮到每個(gè)接口都開一個(gè)線程池,可能線程上下文切換會(huì)消耗很多性能,但是按照NetFlix的測試情況可以發(fā)現(xiàn)因?yàn)榫€程池導(dǎo)致的性能損耗很少,下面就介紹下熔斷隔離的流程。

Screenshot 2017-09-21 14.30.44.png

Hystrix流程說明:
1:每次調(diào)用創(chuàng)建一個(gè)新的HystrixCommand,把依賴調(diào)用封裝在run()方法中.
2:執(zhí)行execute()/queue做同步或異步調(diào)用.
3:判斷熔斷器(circuit-breaker)是否打開,如果打開跳到步驟8,進(jìn)行降級(jí)策略,如果關(guān)閉進(jìn)入步驟.
4:判斷線程池/隊(duì)列/信號(hào)量是否跑滿,如果跑滿進(jìn)入降級(jí)步驟8,否則繼續(xù)后續(xù)步驟.
5:調(diào)用HystrixCommand的run方法.運(yùn)行依賴邏輯
5a:依賴邏輯調(diào)用超時(shí),進(jìn)入步驟8.
6:判斷邏輯是否調(diào)用成功
6a:返回成功調(diào)用結(jié)果
6b:調(diào)用出錯(cuò),進(jìn)入步驟8.
7:計(jì)算熔斷器狀態(tài),所有的運(yùn)行狀態(tài)(成功, 失敗, 拒絕,超時(shí))上報(bào)給熔斷器,用于統(tǒng)計(jì)從而判斷熔斷器狀態(tài).
8:getFallback()降級(jí)邏輯.
以下四種情況將觸發(fā)getFallback調(diào)用:
(1):run()方法拋出非HystrixBadRequestException異常。
(2):run()方法調(diào)用超時(shí)
(3):熔斷器開啟攔截調(diào)用
(4):線程池/隊(duì)列/信號(hào)量是否跑滿
8a:沒有實(shí)現(xiàn)getFallback的Command將直接拋出異常
8b:fallback降級(jí)邏輯調(diào)用成功直接返回
8c:降級(jí)邏輯調(diào)用失敗拋出異常
9:返回執(zhí)行成功結(jié)果

3.Hystrxi參數(shù)詳解

最開始例子可以發(fā)現(xiàn)Hystrix通過注解的方式使用起來是非常簡單的,只要搞清楚里面的各種參數(shù)就能用的很6,我整理了一下各個(gè)參數(shù)的作用,大家可以看下,熟悉下整個(gè)Hystrix的功能。下面這張圖表示了Hystrix的熔斷圖,很好理解,圖片來自官網(wǎng)。

Screenshot 2017-09-21 13.23.21.png

execution

execution.isolation.strategy

表示隔離策略,隔離策略有兩種,一種為線程隔離一種為信號(hào)量隔離,線程隔離是按照并發(fā)請(qǐng)求進(jìn)行線程池?cái)?shù)量進(jìn)行隔離,請(qǐng)求線程全部按照線程池設(shè)置屬性進(jìn)行處理,官方也是推薦使用這種隔離策略,默認(rèn)也是按照線程隔離進(jìn)行處理。信號(hào)隔離也可以用于限制并發(fā)訪問,防止阻塞擴(kuò)散, 與線程隔離最大不同在于執(zhí)行依賴代碼的線程依然是請(qǐng)求線程(該線程需要通過信號(hào)申請(qǐng)),如果客戶端是可信的且可以快速返回(例如系統(tǒng)做了redis或者其他內(nèi)存緩存),可以使用信號(hào)隔離替換線程隔離,降低開銷.信號(hào)量的大小可以動(dòng)態(tài)調(diào)整, 線程池大小不可以動(dòng)態(tài)調(diào)整.

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

execution.isolation.thread.timeoutInMilliseconds

這個(gè)就比較簡單了,表示請(qǐng)求線程總超時(shí)時(shí)間,如果超過這個(gè)設(shè)置的時(shí)間hystrix就會(huì)調(diào)用fallback方法。value的參數(shù)為毫秒,默認(rèn)值為1000ms。

@HystrixCommand(fallbackMethod = "error", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "4000")
    })

execution.timeout.enabled

這個(gè)超時(shí)開關(guān)表示,當(dāng)超時(shí)后是否觸發(fā)fallback方法,默認(rèn)為true。

execution.isolation.semaphore.maxConcurrentRequests

當(dāng)隔離策略使用SEMAPHORE時(shí),最大的并發(fā)請(qǐng)求量,如果請(qǐng)求超過這個(gè)最大值將拒絕后續(xù)的請(qǐng)求,默認(rèn)值為10.

fallbackMethod

這個(gè)屬性就很好理解了,表示當(dāng)觸發(fā)隔離條件的時(shí)候會(huì)調(diào)用fallback設(shè)置的降級(jí)方法,在降級(jí)方法中,我們可以設(shè)置默認(rèn)的降級(jí)返回報(bào)文,這里需要注意的是降級(jí)方法的入?yún)⒑头祷刂敌枰驮椒ㄒ恢?,否則在編譯的時(shí)候會(huì)報(bào)錯(cuò)。

Circuit Breaker熔斷器

circuitBreaker.requestVolumeThreshold

熔斷器在整個(gè)統(tǒng)計(jì)時(shí)間內(nèi)是否開啟的閥值,每個(gè)熔斷器默認(rèn)維護(hù)10個(gè)bucket,每秒一個(gè)bucket,每個(gè)bucket記錄成功,失敗,超時(shí),拒絕的狀態(tài),該閾值默認(rèn)20次。也就是一個(gè)統(tǒng)計(jì)窗口時(shí)間內(nèi)(10秒鐘)至少請(qǐng)求20次,熔斷器才啟動(dòng)。

circuitBreaker.sleepWindowInMilliseconds

熔斷器默認(rèn)工作時(shí)間,默認(rèn)值為5秒.熔斷器中斷請(qǐng)求5秒后會(huì)進(jìn)入半打開狀態(tài),放部分流量過去重試,如果重試成功則會(huì)恢復(fù)正常請(qǐng)求。

circuitBreaker.errorThresholdPercentage

熔斷器錯(cuò)誤閾值,默認(rèn)為50%。當(dāng)在一個(gè)時(shí)間窗口內(nèi)出錯(cuò)率超過50%后熔斷器自動(dòng)啟動(dòng)。熔斷器啟動(dòng)后交易會(huì)自動(dòng)轉(zhuǎn)發(fā)到HystrixCommand的run方法,即配置的fallbackMethod,進(jìn)行降級(jí)處理。但是在中斷開啟后的sleepWindowInMilliseconds時(shí)間后會(huì)進(jìn)行半開放狀態(tài),去正常請(qǐng)求,如果功能恢復(fù)則會(huì)自動(dòng)離開熔斷狀態(tài),恢復(fù)正常請(qǐng)求處理。

circuitBreaker.forceOpen

熔斷器強(qiáng)制開關(guān),如果設(shè)置為true則表示強(qiáng)制打開熔斷器,所有請(qǐng)求都會(huì)拒絕,默認(rèn)為false。

circuitBreaker.forceClosed

與forceOpen正好相反。

ThreadPool Properties

coreSize

線程池核心線程數(shù),默認(rèn)值為10,這里的含義和jdk的線程池一個(gè)意思。

maxQueueSize

該參數(shù)表示配置線程值等待隊(duì)列長度,默認(rèn)值:-1,建議值:-1表示不等待直接拒絕,測試表明線程池使用直接決絕策略+ 合適大小的非回縮線程池效率最高.所以不建議修改此值。 當(dāng)使用非回縮線程池時(shí),queueSizeRejectionThreshold,keepAliveTimeMinutes 參數(shù)無效。

queueSizeRejectionThreshold

表示等待隊(duì)列超過閾值后開始拒絕線程請(qǐng)求,默認(rèn)值為5,如果maxQueueSize為1,則該屬性失效。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,610評(píng)論 19 139
  • (git上的源碼:https://gitee.com/rain7564/spring_microservices_...
    sprainkle閱讀 9,557評(píng)論 13 33
  • 一、認(rèn)識(shí)Hystrix Hystrix是Netflix開源的一款容錯(cuò)框架,包含常用的容錯(cuò)方法:線程池隔離、信號(hào)量隔...
    新棟BOOK閱讀 26,739評(píng)論 1 37
  • 一、認(rèn)識(shí)Hystrix Hystrix是Netflix開源的一款容錯(cuò)框架,包含常用的容錯(cuò)方法:線程池隔離、信號(hào)量隔...
    新棟BOOK閱讀 4,261評(píng)論 0 19
  • 導(dǎo)語:網(wǎng)上資料(尤其中文文檔)對(duì)hystrix基礎(chǔ)功能的解釋比較籠統(tǒng),看了往往一頭霧水。為此,本文將通過若干dem...
    star24閱讀 100,403評(píng)論 36 119

友情鏈接更多精彩內(nèi)容