1.Hystrix是什么?
hystrix對應(yīng)的中文名字是“豪豬”残炮,豪豬周身長滿了刺半等,能保護自己不受天敵的傷害,代表了一種防御機制拾氓,這與hystrix本身的功能不謀而合冯挎,因此Netflix團隊將該框架命名為Hystrix,并使用了對應(yīng)的卡通形象做作為logo咙鞍。
在一個分布式系統(tǒng)里房官,許多依賴不可避免的會調(diào)用失敗,比如超時续滋、異常等翰守,如何能夠保證在一個依賴出問題的情況下,不會導(dǎo)致整體服務(wù)失敗疲酌,這個就是Hystrix需要做的事情蜡峰。Hystrix提供了熔斷了袁、隔離、Fallback湿颅、cache载绿、監(jiān)控等功能,能夠在一個油航、或多個依賴同時出現(xiàn)問題時保證系統(tǒng)依然可用崭庸。
2.用一個例子快速進入Hystrix
Hystrix的核心功能,就是在調(diào)用遠程服務(wù)時的熔斷機制劝堪。下面用一個簡單的例子來說明Hystrix的核心功能冀自。
1.例子基于spring-boot,所以首先新建一個空的spring-boot項目秒啦。建項目的過程此處略過熬粗。
2.添加maven依賴:
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>1.5.9</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-metrics-event-stream</artifactId>
<version>1.5.9</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-javanica</artifactId>
<version>1.5.9</version>
</dependency>
3.新建configuration類
package com.mogujie.marketing.hystrixTest.configuration;
import com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HystrixConfiguration {
@Bean
public HystrixCommandAspect hystrixAspect() {
return new HystrixCommandAspect();
}
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet() {
ServletRegistrationBean registration = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
registration.addUrlMappings("/hystrix.stream");
return registration;
}
}
4.新建RemoteService,代表依賴的遠程服務(wù)余境。
package com.mogujie.marketing.hystrixTest.service;
import org.springframework.stereotype.Service;
@Service("remoteService")
public class RemoteService {
public Object getUser() {
Thread.sleep(2500);
return "user";
}
}
5.新建UserController驻呐,調(diào)用遠程服務(wù)。
package com.mogujie.marketing.hystrixTest.controller;
import com.mogujie.marketing.hystrixTest.service.RemoteService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping({"/test"})
public class UserController {
@Autowired
private RemoteService remoteService;
@RequestMapping(value = "/user")
@HystrixCommand(fallbackMethod = "fallback", threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "30"), @HystrixProperty(name = "maxQueueSize", value = "100"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "20")}, commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "1")
})
public Object getUser() throws InterruptedException {
Object user = remoteService.getUser();
return user;
}
public Object fallback(Throwable e) {
e.printStackTrace();
return "test";
}
}
6.瀏覽器調(diào)用http://127.0.0.1/test/user
可以看到正常返回的結(jié)果芳来。調(diào)整Thread.sleep的時間為3000含末,可以看到fallback函數(shù)返回的結(jié)果。
從上面的例子可以快速體會到Hystrix給遠程服務(wù)調(diào)用帶來的好處即舌,只需要簡單的配置一個注解佣盒,就能給遠程服務(wù)加上超時時間&錯誤回調(diào)。
Hystrix可以支持RPC顽聂、DB肥惭、HTTP等遠程服務(wù)的超時&錯誤回調(diào),甚至可以做本地服務(wù)的超時&錯誤回調(diào)紊搪。剛剛的例子就是模擬本地服務(wù)執(zhí)行超時的情況蜜葱。
一般來說,RPC框架都有基本的超時機制耀石,但是錯誤處理和功能降級往往要自己來實現(xiàn)牵囤,Hystrix幫我省略了這部分冗余的代碼,只需要寫一個回調(diào)函數(shù)滞伟,簡單配置一下就完工了揭鳞。
3.Hystrix的配置項
那Hystrix有哪些配置項?那些配置項又支持哪些功能诗良?這些功能又在什么情況下被用到呢汹桦?解決這些問題是Hystrix進階的關(guān)鍵。
3.1 Hystrix有哪些配置項?
官方配置項地址:配置項詳解.
- execution.isolation.strategy:設(shè)置方法執(zhí)行的隔離策略鉴裹∥杪妫可選線程池或者信號量钥弯。具體分析參考這篇文章Hystrix系列-5-Hystrix的資源隔離策略。
- execution.isolation.thread.timeoutInMilliseconds:設(shè)置調(diào)用者等待命令執(zhí)行的超時限制督禽,超過此時間脆霎,HystrixCommand被標記為TIMEOUT,并執(zhí)行回退邏輯狈惫。
- execution.timeout.enabled:執(zhí)行是否有超時限制睛蛛。
- execution.isolation.thread.interruptOnTimeout:當超時的時候是否中斷
- execution.isolation.thread.interruptOnCancel:當發(fā)生cancel事件后是否中斷
- execution.isolation.semaphore.maxConcurrentRequests:當使用信號量隔離的時候,此配置有效胧谈。官方給出5000請求只需要2個忆肾。
- fallback.isolation.semaphore.maxConcurrentRequests:最大并發(fā)數(shù),超過此并發(fā)則拒絕請求菱肖。
- fallback.enabled:是否打開降級
- circuitBreaker.enabled:是否打開熔斷器客冈。
- circuitBreaker.requestVolumeThreshold:時間窗口內(nèi)最小請求數(shù),當小于這個請求數(shù)稳强,即使全部失敗也不會熔斷场仲。
- circuitBreaker.sleepWindowInMilliseconds:熔斷后,請求retry的時間間隔
- circuitBreaker.errorThresholdPercentage:失敗率閾值退疫,超過這個失敗率就會熔斷
- circuitBreaker.forceOpen:是否強制開啟熔斷渠缕,這樣會導(dǎo)致拒絕所有請求
- circuitBreaker.forceClosed:是否強制關(guān)閉熔斷,這樣任何原因都無法觸發(fā)熔斷褒繁。注:優(yōu)先級小于強制開啟亦鳞。
- metrics.rollingStats.timeInMilliseconds:設(shè)置統(tǒng)計滾動窗口的長度,以毫秒為單位棒坏。用于監(jiān)控和熔斷器蚜迅。
滾動窗口被分隔成桶(bucket)。并進行滾動俊抵。 例如這個屬性設(shè)置10000ms,一個桶就是1s坐梯。 - metrics.rollingStats.numBuckets :統(tǒng)計窗口的桶數(shù)量徽诲。
- metrics.rollingPercentile.enabled:執(zhí)行時間是否被跟蹤,并且計算各個百分比吵血,50%,90%等的時間谎替。
- metrics.rollingPercentile.timeInMilliseconds:設(shè)置執(zhí)行時間在滾動窗口中保留時間,用來計算百分比蹋辅。
- metrics.rollingPercentile.numBuckets:設(shè)置rollingPercentile窗口的桶數(shù)量钱贯。
- metrics.rollingPercentile.bucketSize :設(shè)置每個桶保存的執(zhí)行時間的最大值。
- metrics.healthSnapshot.intervalInMilliseconds:采樣時間間隔侦另。
- requestCache.enabled:設(shè)置是否緩存請求秩命,request-scope內(nèi)緩存尉共。hystrix支持將一個請求結(jié)果緩存起來,下一個具有相同key的請求將直接從緩存中取出結(jié)果弃锐,減少請求開銷袄友。要使用該功能必須管理HystrixRequestContext,如果請求B要用到請求A的結(jié)果緩存霹菊,A和B必須同處一個context剧蚣。
- requestLog.enabled:設(shè)置HystrixCommand執(zhí)行和事件是否打印到HystrixRequestLog中 。
- maxRequestsInBatch:請求合并的最大請求數(shù)
- timerDelayInMilliseconds:請求合并的時間窗口旋廷,也就是出現(xiàn)第一個請求后鸠按,在該時間間隔內(nèi)的請求合并,超過則進入下一個時間窗口
- requestCache.enabled:請求合并是否打開請求緩存
Thread Pool Properties 線程池參數(shù)
- coreSize:線程池的大小
- maximumSize:線程池的最大大小饶碘,只會在設(shè)置了allowMaximumSizeToDivergeFromCoreSize的情況下生效目尖,一般情況下和線程池大小相同。
- maxQueueSize:
-1
代表使用SynchronousQueue熊镣,其它值代表LinkedBlockingQueue.這兩個隊列用于ThreadPoolExecutor - queueSizeRejectionThreshold:隊列拒絕服務(wù)的閾值
- keepAliveTimeMinutes:如果線程池的最大值大于線程池的大小卑雁,那么這個配置用于回收多久沒被使用的線程。
- allowMaximumSizeToDivergeFromCoreSize:線程池的最大值是否可以和線程池的值不一樣
- metrics.rollingStats.timeInMilliseconds:設(shè)置統(tǒng)計滾動窗口的長度绪囱,以毫秒為單位测蹲。用于監(jiān)控和熔斷器。滾動窗口被分隔成桶(bucket)鬼吵。并進行滾動扣甲。 例如這個屬性設(shè)置10000ms,一個桶就是1s齿椅。
- metrics.rollingStats.numBuckets:統(tǒng)計窗口的桶數(shù)量
3.2 Hystrix配置解析
- Execution分組下的配置項琉挖,指定了方法執(zhí)行的隔離策略、超時限制等屬性涣脚。
- Fallback分組下的配置項示辈,指定了最大并發(fā)限制,超過并發(fā)限制則走降級方法遣蚀。
- Circuit Breaker分組下的配置項矾麻,指定了熔斷器的最小請求數(shù)、熔斷之后的重試間隔芭梯、造成熔斷的請求失敗率险耀。
- Metrics分組下的配置項,主要是統(tǒng)計相關(guān)的參數(shù)玖喘,指定了滾動窗口的時間長度甩牺、桶數(shù)量、方法執(zhí)行時間的保留時間等累奈。這塊配置會比較難理解贬派。
- Request Context分組下的配置項急但,指定了是否緩存請求結(jié)果、是否記錄日志赠群。
- Collapser Properties分組下的配置項羊始,用來支持請求合并功能。當單個請求耗時很大的時候查描,可以使用請求合并的方式調(diào)用批量接口突委。設(shè)置最大請求數(shù),合并請求的等待時間冬三,配置請求結(jié)果是否需要緩存匀油。單個請求耗時很低的時候,不建議使用勾笆,反而會降低平均請求時延敌蚜。需要通過評估和計算得出哪種方案更合適窝爪。
- Thread Pool Properties分組下的配置項目,指定了方法執(zhí)行的線程池的初始化參數(shù)蒲每。
4. 實現(xiàn)原理
Hystrix實現(xiàn)了熔斷機制、請求超時邀杏、限流降級、結(jié)果緩存望蜡、請求合并、統(tǒng)計脖律、線程池隔離等功能共同保障應(yīng)用的穩(wěn)定性谢肾。
先來看看官方的流程圖:
分為以下步驟:
1.初始化HystrixCommand
2.執(zhí)行Command
3.是否需要走緩存獲取結(jié)果勒叠?
4.是否已經(jīng)開啟了熔斷?
5.信號量/線程池拒絕請求膏孟?
6.實際執(zhí)行方法
7.上報結(jié)果判斷是否開啟熔斷
8.執(zhí)行失敗走降級方法
9.執(zhí)行成功結(jié)果返回
處理執(zhí)行成功結(jié)果時使用了RxJava(觀察者模式)來傳遞事件,流程如下圖所示:
參考文獻
1.在項目中快速加入Netflix Hystrix特性
2.Hystrix入門指南
3.Hystrix配置簡單說明(官方文檔簡譯)
4.微服務(wù)(二)hystrix
5.Hystrix系列-5-Hystrix的資源隔離策略
6.通過HystrixCollapser合并請求提高應(yīng)用吞吐量
7.How it Works