SpringBoot集成Hystrix

Hystrix配置

@Configuration
public class HystrixConfig {

    @Bean
    public HystrixCommandAspect hystrixCommandAspect() {
        return new HystrixCommandAspect();
    }

    /**
     * 向監(jiān)控中心Dashboard發(fā)送stream消息
     */
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet() {
        ServletRegistrationBean registrationBean =
                new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        registrationBean.addUrlMappings("/hystrix.stream");
        return registrationBean;
    }
}

Hystrix配置參數(shù)講解:

// 熔斷器在整個統(tǒng)計時間內(nèi)是否開啟的閥值
 @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
 // 至少有3個請求才進(jìn)行熔斷錯誤比率計算
 /**
  * 設(shè)置在一個滾動窗口中,打開斷路器的最少請求數(shù)脊僚。
  比如:如果值是20,在一個窗口內(nèi)(比如10秒),收到19個請求鸠姨,即使這19個請求都失敗了择膝,斷路器也不會打開。
  */
 @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "3"),
 //當(dāng)出錯率超過50%后熔斷器啟動
 @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
 // 熔斷器工作時間油湖,超過這個時間巍扛,先放一個請求進(jìn)去,成功的話就關(guān)閉熔斷乏德,失敗就再等一段時間
 @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000")
@HystrixProperty(name = "coreSize", value = "30"),
 /**
  * BlockingQueue的最大隊列數(shù)撤奸,當(dāng)設(shè)為-1,會使用SynchronousQueue喊括,值為正時使用LinkedBlcokingQueue胧瓜。
  */
 @HystrixProperty(name = "maxQueueSize", value = "101"),
 /**
  * 設(shè)置存活時間,單位分鐘瘾晃。如果coreSize小于maximumSize贷痪,那么該屬性控制一個線程從實用完成到被釋放的時間.
  */

/**
  我們知道,線程池內(nèi)核心線程數(shù)目都在忙碌蹦误,再有新的請求到達(dá)時,線程池容量可以被擴(kuò)充為到最大數(shù)量肉津。
等到線程池空閑后强胰,多于核心數(shù)量的線程還會被回收,此值指定了線程被回收前的存活時間妹沙,默認(rèn)為 2偶洋,即兩分鐘。
*/
 @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
 /**
  * 設(shè)置隊列拒絕的閾值,即使maxQueueSize還沒有達(dá)到
  */
 @HystrixProperty(name = "queueSizeRejectionThreshold", value = "15"),

// 滑動統(tǒng)計的桶數(shù)量
 /**
  * 設(shè)置一個rolling window被劃分的數(shù)量距糖,若numBuckets=10玄窝,rolling window=10000,
  *那么一個bucket的時間即1秒悍引。必須符合rolling window % numberBuckets == 0恩脂。默認(rèn)1
  */
 @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),
 // 設(shè)置滑動窗口的統(tǒng)計時間。熔斷器使用這個時間
 /** 設(shè)置統(tǒng)計的時間窗口值的趣斤,毫秒值俩块。
  circuit break 的打開會根據(jù)1個rolling window的統(tǒng)計來計算。
  若rolling window被設(shè)為10000毫秒浓领,則rolling window會被分成n個buckets玉凯,
  每個bucket包含success,failure联贩,timeout漫仆,rejection的次數(shù)的統(tǒng)計信息。默認(rèn)10000
  **/
 @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000")


fallbackMethod:方法執(zhí)行時熔斷泪幌、錯誤盲厌、超時時會執(zhí)行的回退方法署照,需要保持此方法與 Hystrix 方法的簽名和返回值一致。

defaultFallback:默認(rèn)回退方法狸眼,當(dāng)配置 fallbackMethod 項時此項沒有意義藤树,另外,默認(rèn)回退方法不能有參數(shù)拓萌,返回值要與 Hystrix方法的返回值相同岁钓。

對Hystrix服務(wù)降級和熔斷進(jìn)行測試,3個例子微王。

@RestController
@RequestMapping("/hystrix1")
@DefaultProperties(defaultFallback = "defaultFail")
public class HystrixController1 {

    @HystrixCommand(fallbackMethod = "fail1")
    @GetMapping("/test1")
    public String test1() {
        throw new RuntimeException();
    }

    private String fail1() {
        System.out.println("fail1");
        return "fail1";
    }

    @HystrixCommand(fallbackMethod = "fail2")
    @GetMapping("/test2")
    public String test2() {
        throw new RuntimeException();
    }

    @HystrixCommand(fallbackMethod = "fail3")
    private String fail2() {
        System.out.println("fail2");
        throw new RuntimeException();
    }

    @HystrixCommand
    private String fail3() {
        System.out.println("fail3");
        throw new RuntimeException();
    }

    private String defaultFail() {
        System.out.println("default fail");
        return "default fail";
    }


}

當(dāng)訪問http://localhost:8082/hystrix1/test1拋出異常屡限,服務(wù)降級返回fail1。
當(dāng)訪問http://localhost:8082/hystrix1/test2拋出異常炕倘,服務(wù)不斷降級返回default fail钧大。

image.png
@RestController
@RequestMapping("/hystrix2")
@DefaultProperties(defaultFallback = "defaultFail")
public class HystrixController2 {

    @HystrixCommand(commandProperties =
            {
                    // 熔斷器在整個統(tǒng)計時間內(nèi)是否開啟的閥值
                    @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
                    // 至少有3個請求才進(jìn)行熔斷錯誤比率計算
                    /**
                     * 設(shè)置在一個滾動窗口中,打開斷路器的最少請求數(shù)罩旋。
                     比如:如果值是20啊央,在一個窗口內(nèi)(比如10秒),收到19個請求涨醋,即使這19個請求都失敗了瓜饥,斷路器也不會打開。
                     */
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "3"),
                    //當(dāng)出錯率超過50%后熔斷器啟動
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
                    // 熔斷器工作時間浴骂,超過這個時間乓土,先放一個請求進(jìn)去,成功的話就關(guān)閉熔斷溯警,失敗就再等一段時間
                    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000"),
                    // 統(tǒng)計滾動的時間窗口
                    @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000")
            })
    @GetMapping("/test1")
    public String test1(@RequestParam("id") Integer id) {
        System.out.println("id:" + id);

        if (id % 2 == 0) {
            throw new RuntimeException();
        }
        return "test_" + id;
    }

    private String defaultFail() {
        System.out.println("default fail");
        return "default fail";
    }
}

當(dāng)訪問1次http://localhost:8082/hystrix2/test1?id=1和2次http://localhost:8082/hystrix2/test1?id=2趣苏,錯誤率達(dá)66%超過了設(shè)置的50%。服務(wù)進(jìn)入熔斷梯轻。

image.png

下次請求http://localhost:8082/hystrix2/test1?id=2會進(jìn)入熔斷策略食磕,返回default fail

image.png

如果在5s之后,下一次請求成功檩淋,會關(guān)閉熔斷芬为,服務(wù)恢復(fù)。


image.png
image.png
@RestController
@RequestMapping("/hystrix3")
@DefaultProperties(defaultFallback = "defaultFail")
public class HystrixController3 {

    @HystrixCommand(commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "500")
    })
    @GetMapping("/test1")
    public String test1() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(1000);
        return "test1";
    }

    @HystrixCommand(commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500"),
            // 滑動統(tǒng)計的桶數(shù)量
            /**
             * 設(shè)置一個rolling window被劃分的數(shù)量蟀悦,若numBuckets=10媚朦,rolling window=10000,
             *那么一個bucket的時間即1秒日戈。必須符合rolling window % numberBuckets == 0询张。默認(rèn)1
             */
            @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),
            // 設(shè)置滑動窗口的統(tǒng)計時間。熔斷器使用這個時間
            /** 設(shè)置統(tǒng)計的時間窗口值的浙炼,毫秒值份氧。
             circuit break 的打開會根據(jù)1個rolling window的統(tǒng)計來計算唯袄。
             若rolling window被設(shè)為10000毫秒,則rolling window會被分成n個buckets蜗帜,
             每個bucket包含success恋拷,failure,timeout厅缺,rejection的次數(shù)的統(tǒng)計信息蔬顾。默認(rèn)10000
             **/
            @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000")},
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "15"),
                    /**
                     * BlockingQueue的最大隊列數(shù),當(dāng)設(shè)為-1湘捎,會使用SynchronousQueue诀豁,值為正時使用LinkedBlcokingQueue。
                     */
                    @HystrixProperty(name = "maxQueueSize", value = "15"),
                    /**
                     * 設(shè)置存活時間窥妇,單位分鐘舷胜。如果coreSize小于maximumSize,那么該屬性控制一個線程從實用完成到被釋放的時間.
                     */
                    @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
                    /**
                     * 設(shè)置隊列拒絕的閾值,即使maxQueueSize還沒有達(dá)到
                     */
                    @HystrixProperty(name = "queueSizeRejectionThreshold", value = "15"),
                    @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),
                    @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000")
            })
    @GetMapping("/test2")
    public String test2() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(1000);
        return "test2";
    }

    private String defaultFail() {
        System.out.println("default fail");
        return "default fail";
    }
}


當(dāng).\ab -c 30 -n 30 http://localhost:8082/hystrix3/test1并發(fā)30個請求活翩。

image.png

由于沒有顯式配置maxQueueSize烹骨。Hystrix不會向阻塞隊列里面放任務(wù)。當(dāng)任務(wù)的數(shù)量超過了線程池負(fù)載的閾值材泄,會采用拒絕任務(wù)策略展氓。核心線程數(shù)量+初始數(shù)量=11個線程。11個線程由于線程阻塞進(jìn)入了Timeout狀態(tài)脸爱,后續(xù)無法正常繼續(xù)執(zhí)行其他任務(wù),采取拒絕任務(wù)策略(拒絕了30-11=19個任務(wù))未妹。

此時服務(wù)進(jìn)入到熔斷狀態(tài)簿废,在5s之后,我們再發(fā)送http://localhost:8082/hystrix3/test1請求络它,發(fā)現(xiàn)還是處于timeout狀態(tài)族檬,依舊是失敗,繼續(xù)保持熔斷狀態(tài)化戳。

image.png

后續(xù)再發(fā)送http://localhost:8082/hystrix3/test1請求单料,該請求已經(jīng)進(jìn)入到熔斷處理。

image.png

maxQueueSize:作業(yè)隊列的最大值点楼,默認(rèn)值為 -1扫尖,設(shè)置為此值時,隊列會使用 SynchronousQueue掠廓,此時其 size 為0换怖。
Hystrix 不會向隊列內(nèi)存放作業(yè)。如果此值設(shè)置為一個正的 int 型蟀瞧,隊列會使用一個固定 size 的 LinkedBlockingQueue沉颂。
此時在核心線程池內(nèi)的線程都在忙碌時条摸,會將作業(yè)暫時存放在此隊列內(nèi),但超出此隊列的請求依然會被拒絕铸屉。

queueSizeRejectionThreshold:由于 maxQueueSize 值在線程池被創(chuàng)建后就固定了大小钉蒲,
如果需要動態(tài)修改隊列長度的話可以設(shè)置此值,
即使隊列未滿彻坛,隊列內(nèi)作業(yè)達(dá)到此值時同樣會拒絕請求顷啼。
此值默認(rèn)是 5,所以有時候只設(shè)置了 maxQueueSize 也不會起作用小压。

image.png

當(dāng).\ab -c 100 -n 100 http://localhost:8082/hystrix3/test2并發(fā)100個請求线梗。核心線程數(shù)是15個,加上初始的1個怠益。核心線程數(shù)應(yīng)該是16個仪搔,阻塞隊列里面有15個。所以executions為31個蜻牢。當(dāng)線程數(shù)超過了阻塞隊列的閾值烤咧,就拒絕任務(wù),所以Rejected的數(shù)量是100-31=69個抢呆。默認(rèn)情況下煮嫌,在滑動窗口內(nèi),請求數(shù)量超過了20個抱虐,才計算熔斷錯誤比率昌阿。當(dāng)熔斷錯誤比率超過了50%,采用熔斷策略恳邀。

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末懦冰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子谣沸,更是在濱河造成了極大的恐慌刷钢,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,222評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乳附,死亡現(xiàn)場離奇詭異内地,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)赋除,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評論 3 385
  • 文/潘曉璐 我一進(jìn)店門阱缓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人贤重,你說我怎么就攤上這事茬祷。” “怎么了?”我有些...
    開封第一講書人閱讀 157,720評論 0 348
  • 文/不壞的土叔 我叫張陵祭犯,是天一觀的道長秸妥。 經(jīng)常有香客問我,道長沃粗,這世上最難降的妖魔是什么粥惧? 我笑而不...
    開封第一講書人閱讀 56,568評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮最盅,結(jié)果婚禮上突雪,老公的妹妹穿的比我還像新娘。我一直安慰自己涡贱,他們只是感情好咏删,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,696評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著问词,像睡著了一般督函。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上激挪,一...
    開封第一講書人閱讀 49,879評論 1 290
  • 那天辰狡,我揣著相機(jī)與錄音,去河邊找鬼垄分。 笑死宛篇,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的薄湿。 我是一名探鬼主播叫倍,決...
    沈念sama閱讀 39,028評論 3 409
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼豺瘤!你這毒婦竟也來了段标?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,773評論 0 268
  • 序言:老撾萬榮一對情侶失蹤炉奴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蛇更,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞻赶,經(jīng)...
    沈念sama閱讀 44,220評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,550評論 2 327
  • 正文 我和宋清朗相戀三年派任,在試婚紗的時候發(fā)現(xiàn)自己被綠了砸逊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,697評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡掌逛,死狀恐怖师逸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情豆混,我是刑警寧澤篓像,帶...
    沈念sama閱讀 34,360評論 4 332
  • 正文 年R本政府宣布动知,位于F島的核電站,受9級特大地震影響员辩,放射性物質(zhì)發(fā)生泄漏盒粮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,002評論 3 315
  • 文/蒙蒙 一奠滑、第九天 我趴在偏房一處隱蔽的房頂上張望丹皱。 院中可真熱鬧,春花似錦宋税、人聲如沸摊崭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,782評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呢簸。三九已至,卻和暖如春淆攻,著一層夾襖步出監(jiān)牢的瞬間阔墩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,010評論 1 266
  • 我被黑心中介騙來泰國打工瓶珊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留啸箫,地道東北人。 一個月前我還...
    沈念sama閱讀 46,433評論 2 360
  • 正文 我出身青樓伞芹,卻偏偏與公主長得像忘苛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子唱较,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,587評論 2 350

推薦閱讀更多精彩內(nèi)容