SpringCloud之Hystrix断路器(熔断、限流、降级、超时监控)
hystrix是什么?
Hystrix是一個用于處理分布式系統的延遲和容錯的開源庫,在分布式系統里,許多依賴不可避免的會調用失敗,比如超時、異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障,以提高分布式系統的彈性。
“斷路器”本身是一種開關裝置,當某個服務單元發生故障之后,通過斷路器的故障監控(類似熔斷保險絲),向調用方返回一個符合預期的、可處理的備選響應(FallBack),而不是長時間的等待或者拋出調用方無法處理的異常,這樣就保證了服務調用方的線程不會被長時間、不必要地占用,從而避免了故障在分布式系統中的蔓延,乃至雪崩。
服務雪崩效應
聯想一下上圖, 如果發生這種情況, 也就是說所有發給微服務D的請求 都會被卡在微服務H那, 就會導致線程一直累計在這里, 那么其他的微服務(比如A,B,C...) 就沒有可用線程了, 導致整個服務器
崩潰,這就是服務血崩。
導致服務雪崩的情況我們來總結一下,再看看怎么解決:
程序BUG,數據不匹配,響應時間過長,服務不可用等等.....
針對上面的問題,我們來看看有哪些解決方案 :
服務限流
超時監控
服務熔斷
服務降級
降級,超時 :
降級是當我們的某個微服務響應時間過長,或者不可用了,講白了也就是那個微服務調用不了了,我們不能吧錯誤信息返回出來,或者讓他一直卡在那里,所以要在準備一個對應的策略(一個方法)當發生
這種問題的時候我們直接調用這個方法來快速返回這個請求,不讓他一直卡在那 。
來看看具體怎么操作:
某個微服務調用不了了要做降級,也就是說,要在調用方做降級(不然那個微服務都down掉了再做降級也沒什么意義了) 比如說我們 user 調用power 那么就在user(即客戶端) 做降級。
添加Hystrix依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
啟動類加入注解@EnableHystrix 或者@EnableCircuitBreaker
然后在我們的controller上面加入注解@HystrixCommand(fallbackMethod就是我們剛剛說的方法的名字)
@RequestMapping("/feignPower.do")
@HystrixCommand(fallbackMethod = "fallbackMethod")
public Object feignPower(String name){
return powerServiceClient.power();
}
fallbackMethod:
public Object fallbackMethod(String name){
System.out.println(name);
return R.error("降級信息");
}
這里的這個降級信息具體內容得根據業務需求來, 比如說返回一個默認的查詢信息,亦或是系統維護(因為有可能要暫時關閉某個微服務而吧資源讓給其他服務)等等...
這時我們可以在power服務的power方法中制作一個異常即可自動調用fallbackMethod方法完成降級。
超時的情況也是如此,只需將在power方法中睡眠個幾秒鐘即可完成超時。
因為hystrix他有默認的超時監聽,當你這個請求默認超過了1秒鐘就會超時 當然,這個可以配置的。
降級到底有什么實際作用?
他可以監聽你的請求有沒有超時
報錯了他這里直接截斷了沒有讓請求一直卡在這里
整體資源快不夠了,忍痛將某些服務先關掉,把資源讓給主服務。就是當你的系統馬上迎來大量的并發(雙十一秒殺這種 或者促銷活動) 這時候如果發現系統馬上承載不了這么大的并發時, 可以考慮先關閉一些不重要的微服務(在降級方法里面返回一個比較友好的信息)
熔斷,限流:
其實熔斷,就好像我們生活中的跳閘一樣, 比如說你的電路出故障了,為了防止出現大型事故 這里直接切斷了你的電源以免意外繼續發生, 把這個概念放在我們程序上也是如此, 當一個微服務調用多
次出現問題時(默認是10秒內20次當然 這個也能配置),hystrix就會采取熔斷機制,不再繼續調用你的方法(會在默認5秒鐘內和電器短路一樣,5秒鐘后會試探性的先關閉熔斷機制,但是如果這時候再失敗一次{之前是20次}那么又會重新進行熔斷) 而是直接調用降級方法,這樣就一定程度上避免了服務雪崩的問題。
限流
限流, 顧名思義, 就是限制你某個微服務的使用量(可用線程)
hystrix通過線程池的方式來管理你的微服務調用,他默認是一個線程池(10大小) 管理你的所有微服務,你可以給某個微服務開辟新的線程池:
@RequestMapping("/feignOrder.do")
@HystrixCommand(fallbackMethod = "fallbackOrderMethod" ,
threadPoolKey = "order",
threadPoolProperties ={@HystrixProperty(name = "coreSize",value = "2")
,@HystrixProperty(name = "maxQueueSize",value = "1"})
public Object feignOrder(String name){
System.out.println(1);
return restTemplate.getForObject(ORDERURL+"/order.do",Object.class);
}
threadPoolKey 就是在線程池唯一標識, hystrix 會拿你這個標識去計數,看線程占用是否超過了, 超過了就會直接降級該次調用
比如, 這里coreSize給他值為2 那么假設你這個方法調用時間是3s執行完, 那么在3s內如果有超過2個請求進來的話, 剩下的請求則全部降級
feign整合hystrix:
feign 默認是支持hystrix的, 但是在Spring - cloud Dalston 版本之后就默認關閉了, 因為不一定業務需求要用的到
所以現在要使用首先得打開他,在yml文件加上如下配置:
feign: hystrix: enabled: true
加上配置之后降級方法怎么寫呢?
@FeignClient(value = "SERVER-POWER",fallback = PowerServiceFallBack.class)
public interface PowerServiceClient {
@RequestMapping("/power.do")
public Object power(@RequestParam("name") String name);
}
在feign客戶端的注解上 有個屬性叫fallback 然后指向一個類
PowerServiceFallBack 類:
@Component
public class PowerServiceFallBack implements PowerServiceClient {
@Override
public Object power(String name) {
return R.error("測試降級");
}
}
這樣子,方法降級就寫好了
當然 可能你有這種需求, 需要拿到具體的錯誤信息, 那么可以這樣寫:
@Component
public class PowerServiceClientFallBackFactory implements
FallbackFactory<PowerServiceClient> {
@Override
public PowerServiceClient create(Throwable throwable) {
return new PowerServiceClient() {
@Override
public Object power(String name) {
String message = throwable.getMessage();
return R.error("feign降級");
}
};
}
}
客戶端指定一個fallbackFactory就好了
@FeignClient(value = "SERVER-POWER",fallbackFactory =
PowerServiceClientFallBackFactory.class)
public interface PowerServiceClient {
@RequestMapping("/power.do")
public Object power(@RequestParam("name") String name);
}
這個message 就是拿到的錯誤信息
至此, 就完成了feign與hystrix的整合
hystrix相關配置:
Execution相關的屬性的配置 hystrix.command.default.execution.isolation.strategy隔離策略,默認是Thread,可選Thread|Semaphor hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds命令執行超時時間,默認1000ms hystrix.command.default.execution.timeout.enabled執行是否啟用超時,默認啟用true hystrix.command.default.execution.isolation.thread.interruptOnTimeout發生超時是是否中斷,默認true hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests最大并發請求數,默認10,該參數當使用ExecutionIsolationStrategy.SEMAPHORE策略時才有效。如果達到最大并發請求 數,請求會被拒絕。理論上選擇semaphoresize的原則和選擇threadsize一致,但選用semaphore時每次執行的單元要比較小且執行速度快(ms級別),否則的話應該用thread。 semaphore應該占整個容器(tomcat)的線程 池的一小部分。 Fallback相關的屬性 這些參數可以應用于Hystrix的THREAD和SEMAPHORE策略 hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests如果并發數達到該設置值,請求會被拒絕和拋出異常并且fallback不會被調用。默認10 hystrix.command.default.fallback.enabled當執行失敗或者請求被拒絕,是否會嘗試調用 hystrixCommand.getFallback()。默認true CircuitBreaker相關的屬性 hystrix.command.default.circuitBreaker.enabled用來跟蹤circuit的健康性,如果未達標則讓request短路。默認true hystrix.command.default.circuitBreaker.requestVolumeThreshold一個rollingwindow內最小的請 求數。如果設為20,那么當一個rollingwindow的時間內(比如說1個rollingwindow是10秒)收到19個請 求, 即使19個請求都失敗,也不會觸發circuitbreak。默認20 hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds觸發短路的時間值,當該值設為5000時,則當觸發circuitbreak后的5000毫秒內都會拒絕request,也就是5000毫秒后才會關閉circuit。 默認5000 hystrix.command.default.circuitBreaker.errorThresholdPercentage錯誤比率閥值,如果錯誤率>=該值,circuit會被打開,并短路所有請求觸發fallback。默認50 hystrix.command.default.circuitBreaker.forceOpen強制打開熔斷器,如果打開這個開關,那么拒絕所有request,默認false hystrix.command.default.circuitBreaker.forceClosed強制關閉熔斷器如果這個開關打開,circuit將一直關閉且忽略circuitBreaker.errorThresholdPercentageMetrics相關參數 hystrix.command.default.metrics.rollingStats.timeInMilliseconds設置統計的時間窗口值的,毫秒值,circuitbreak的打開會根據1個rollingwindow的統計來計算。若rollingwindow被設為10000毫秒, 則rollingwindow會被分成n個buckets,每個bucket包含success,failure,timeout,rejection的次數的統計信息。默認10000 hystrix.command.default.metrics.rollingStats.numBuckets設置一個rollingwindow被劃分的數量,若numBuckets=10,rollingwindow=10000,那么一個bucket的時間即1秒。必須符合rollingwindow%numberBuckets==0。默認10 hystrix.command.default.metrics.rollingPercentile.enabled執行時是否enable指標的計算和跟蹤,默認true hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds設置rollingpercentilewindow的時間,默認60000 hystrix.command.default.metrics.rollingPercentile.numBuckets設置rollingpercentilewindow的numberBuckets。邏輯同上。默認6 hystrix.command.default.metrics.rollingPercentile.bucketSize如果bucketsize=100,window =10s,若這10s里有500次執行,只有最后100次執行會被統計到bucket里去。增加該值會增加內存開銷以及排序 的開銷。默認100 hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds記錄health快照(用 來統計成功和錯誤綠)的間隔,默認500ms RequestContext相關參數 hystrix.command.default.requestCache.enabled默認true,需要重載getCacheKey(),返回null時不緩存 hystrix.command.default.requestLog.enabled記錄日志到HystrixRequestLog,默認true CollapserProperties相關參數 hystrix.collapser.default.maxRequestsInBatch單次批處理的最大請求數,達到該數量觸發批處理,默認 Integer.MAX_VALU hystrix.collapser.default.timerDelayInMilliseconds觸發批處理的延遲,也可以為創建批處理的時間+該值,默認10 hystrix.collapser.default.requestCache.enabled是否對HystrixCollapser.execute()and HystrixCollapser.queue()的cache,默認true ThreadPool相關參數 線程數默認值10適用于大部分情況(有時可以設置得更小),如果需要設置得更大,那有個基本得公式可以 follow: requestspersecondatpeakwhenhealthy×99thpercentilelatencyinseconds+some breathingroom 每秒最大支撐的請求數(99%平均響應時間+緩存值) 比如:每秒能處理1000個請求,99%的請求響應時間是60ms,那么公式是: 1000(0.060+0.012)基本得原則時保持線程池盡可能小,他主要是為了釋放壓力,防止資源被阻塞。 當一切都是正常的時候,線程池一般 僅會有1到2個線程激活來提供服務 hystrix.threadpool.default.coreSize并發執行的最大線程數,默認10 hystrix.threadpool.default.maxQueueSizeBlockingQueue的最大隊列數,當設為-1,會使用 SynchronousQueue,值為正時使用LinkedBlcokingQueue。該設置只會在初始化時有效,之后不能修改 threadpool的queuesize,除非reinitialisingthreadexecutor。默認-1。 hystrix.threadpool.default.queueSizeRejectionThreshold即使maxQueueSize沒有達到,達到queueSizeRejectionThreshold該值后,請求也會被拒絕。因為maxQueueSize不能被動態修改,這個參數將允許我們動態設置該值。ifmaxQueueSize==•1,該字段將不起作用 hystrix.threadpool.default.keepAliveTimeMinutes如果corePoolSize和maxPoolSize設成一樣(默認 實現)該設置無效。如果通過plugin(https://github.com/Netflix/Hystrix/wiki/Plugins)使用自定義 實現,該設置才有用,默認1. hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds線程池統計指標的時間,默認10000 hystrix.threadpool.default.metrics.rollingStats.numBuckets將rollingwindow劃分為n個buckets,默認10
總結
以上是生活随笔為你收集整理的SpringCloud之Hystrix断路器(熔断、限流、降级、超时监控)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 华三防火墙实用操作
 - 下一篇: 流产后吃什么好(小产坐月子注意事项!)