輕攏慢捻,談微服務(wù)熔斷大總管
我這篇文章來的晚了些,因為hystrix已經(jīng)進入維護模式。但已經(jīng)有非常多的同學(xué)入坑了,那么本篇文章就是及時雨。本文將說明熔斷使用的一些注意事項,可能會細的讓你厭煩。
前半段,是理論部分,各種熔斷都適用。后半段,是參數(shù)部分,適合微調(diào)。
那我們開始。
通常來說,皇帝在微服務(wù)里想夜生活過得舒服,能夠大刀闊斧單刀直入,不因私事丟江山,就不得不靠熔斷大總管。
時過境遷。提到熔斷大總管就不得不說他手下最突出的三位公公:sentinel,或hystrix,也可能是resilience4j。
這三位都是解決一類問題的,如著名的雪崩:A→B→C互相依次調(diào)用,但C項目很可能出現(xiàn)問題(流量過大或者報錯等),引發(fā)線程一直進行等待,導(dǎo)致拖垮整個鏈路層,線程資源耗盡。
一、背景
假如是用的spring全家桶系列,在接口調(diào)用上大多會走這個路線。我們這里依然是在說hystrix,雖然現(xiàn)在不再受寵。
Feign —-→
Hystrix —-→
Ribbon —-→
Http Client(apache http components/Okhttp)
具體如下圖所示:
二、配置
首先來點理論性的東西。好吃不貴。
Ⅰ隔離方式
線程隔離(默認):使用一個線程池來存儲當(dāng)前的請求,線程池對請求作處理,設(shè)置任務(wù)返回處理超時時間,堆積的請求堆積入線程池隊列。這種方式需要為每個依賴的服務(wù)申請線程池,有一定的資源消耗,好處是可以應(yīng)對突發(fā)流量(流量洪峰來臨時,處理不完可將數(shù)據(jù)存儲到線程池隊里慢慢處理)
信號隔離:使用一個原子計數(shù)器(或信號量)來記錄當(dāng)前有多少個線程在運行,請求來先判斷計數(shù)器的數(shù)值,若超過設(shè)置的最大線程個數(shù)則丟棄改類型的新請求,若不超過則執(zhí)行計數(shù)操作請求來計數(shù)器+1,請求返回計數(shù)器-1。這種方式是嚴格的控制線程且立即返回模式,無法應(yīng)對突發(fā)流量(流量洪峰來臨時,處理的線程超過數(shù)量,其他的請求會直接返回,不繼續(xù)去請求依賴的服務(wù))
Ⅱ熔斷
如果某個目標服務(wù)調(diào)用慢或者大量超時,則此時熔斷該服務(wù)的調(diào)用,對于后續(xù)調(diào)用請求,不再繼續(xù)調(diào)用目標服務(wù),直接返回,快速釋放資源。如果目標服務(wù)情況好轉(zhuǎn),則恢復(fù)調(diào)用。
這個過程,可以想象成保險絲的行為。
行為雖然簡單,但需要調(diào)節(jié)的參數(shù)卻非常多。
使用方式
1.引入依賴
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-hystrix</artifactId>
- </dependency>
2.配置參數(shù)
- feign:
- hystrix:
- #不配置或為false則不生效
- enabled: true
- hystrix:
- command:
- default:
- execution:
- isolation:
- thread:
- #若配置了重試則超時時間= (1 + MaxAutoRetries + MaxAutoRetriesNextServer) * ReadTimeout
- timeoutInMilliseconds: 60000
- threadpool:
- default:
- coreSize: 10
- maxQueueSize: 50
- queueSizeRejectionThreshold: 30
- keepAliveTimeMinutes: 3
3.配置fallback
因業(yè)務(wù)處理不同,建議每個feign client使用不同的fallback
到此,hystrix已經(jīng)可以走馬上任,至于干活兒穩(wěn)不穩(wěn)那是后話。
4.配置的其他姿勢
hystrix到任務(wù)后,發(fā)現(xiàn)有的服務(wù)接口1s內(nèi)就完事兒 ,還有的5s到10幾秒才堪堪返回。一刀切的配置已難以管理諸多服務(wù)&接口。
想必已經(jīng)有人發(fā)現(xiàn),之前配置中混進了奇怪的東西——default關(guān)鍵詞。這是對全局配置,那么對應(yīng)的肯定有局部的配置。
如:對服務(wù)的,對某個接口的…
- hystrix:
- command:
- default:
- execution:
- isolation:
- thread:
- timeoutInMilliseconds: 60000
- threadpool:
- #全局配置
- default:
- coreSize: 10
- maxQueueSize: 50
- queueSizeRejectionThreshold: 30
- keepAliveTimeMinutes: 3
- #對某個服務(wù)配置,寫service-id
- base-rpc:
- coreSize: 10
- maxQueueSize: 30
- queueSizeRejectionThreshold: 20
- keepAliveTimeMinutes: 3
- #對某個接口配置
- BaseApiClient#searchItemSkuList(PosSkuSearch):
- coreSize: 10
- maxQueueSize: 40
- queueSizeRejectionThreshold: 30
- keepAliveTimeMinutes: 1
另外,還可以使用@HystrixCommand注解進行配置。
5.配置的動態(tài)修改
很多情況下,不能修改個配置,特別是臨時修改配置就重啟下服務(wù),能動態(tài)刷新就最好了。
于是我們盯上了hystrix使用archaius管理配置的問題。
archaius是Netflix公司開源項目之一,基于java的配置管理類庫,主要用于多配置存儲的動態(tài)獲取。
主要功能是對apache common configuration類庫的擴展。在云平臺開發(fā)中可以將其用作分布式配置管理依賴構(gòu)件。同時,它有如下一些特性:
動態(tài)獲取屬性
高效和線程安全的配置操作
配置改變時提供回調(diào)機制
可以通過jmx操作配置
復(fù)合配置
說了這么多那該怎么整呢?以下就是簡單的示例。
- //撈配置
- AbstractConfiguration config = ConfigurationManager.getConfigInstance();
- //提取關(guān)注的部分,比如hystrix.threadpool
- Iterable<String> iterable = () -> config.getKeys("hystrix.threadpool");
- List<Property> result = StreamSupport.stream(iterable.spliterator(), false).map(t -> new Property(t, config.getString(t, "")))
- .sorted(Comparator.comparing(Property::getName)).collect(Collectors.toList());
- //修改配置
- config.setProperty("hystrix.threadpool.base-rpc.coreSize", 20);
- //移除配置
- config.clearProperty(hystrix.threadpool.base-rpc.coreSize");
三、其他參數(shù)
要是覺得hystrix這么聽話,那就太小看它了。別忘了前面有feign,后面還有ribbon,再往后http client呢!一堆超時參數(shù),當(dāng)代的八門金鎖陣
1.feign超時
- feign:
- hystrix:
- enabled: true
- client:
- config:
- default:
- connectTimeout: 5000
- readTimeout: 5000
- rpc-pos:
- connectTimeout: 5000
- readTimeout: 8000
- xx-rpc:
- connectTimeout: 5000
- readTimeout: 12000
- order-rpc:
- connectTimeout: 5000
- readTimeout: 8000
feign是暴露給用戶使用的,Spring在處理這一塊的時候,會有意識地使用feign的超時時間來設(shè)置后面的ribbon 和http client組件。
2.ribbon超時
- #全局配置
- ribbon:
- ReadTimeout: 60000
- ConnectTimeout: 10000
- #false to only allow get method to retry
- OkToRetryOnAllOperations: true
- # Max number of next servers to retry (excluding the first server)
- MaxAutoRetriesNextServer: 2
- # Max number of retries on the same server (excluding the first try)
- MaxAutoRetries: 0
- # Interval to refresh the server list from the source
- ServerListRefreshInterval: 5000
- retryableStatusCodes: 404,500
- #服務(wù)配置
- base-rpc:
- ribbon:
- ReadTimeout: 60000
- ConnectTimeout: 10000
- #false to only allow get method to retry
- OkToRetryOnAllOperations: true
- # Max number of next servers to retry (excluding the first server)
- MaxAutoRetriesNextServer: 2
- # Max number of retries on the same server (excluding the first try)
- MaxAutoRetries: 0
- # Interval to refresh the server list from the source
- ServerListRefreshInterval: 5000
- retryableStatusCodes: 404,500
當(dāng)feign設(shè)置了超時時間,Ribbon會依據(jù)feign的設(shè)置同步。Ribbon的這個超時時間,用于指導(dǎo)真正調(diào)用接口時,設(shè)置真正實現(xiàn)者的超時時間。
httpclient超時
- feign:
- hystrix:
- enabled: true
- okhttp:
- enabled: true
- httpclient:
- enabled: false
- //連接池最大連接數(shù),默認200
- max-connections: 500
- //每一個IP最大占用多少連接 默認 50
- max-connections-per-route: 50
- //默認連接超時時間:2000毫秒
- connection-timeout: 8000
- //連接池管理定時器執(zhí)行頻率:默認 3000毫秒
- connection-timer-repeat: 6000
- //連接池中存活時間,默認為5
- time-to-live: 5
- time-to-live-unit: minutes
超時設(shè)置遵循的基本原則是:依賴方的超時配置覆蓋被依賴方的配置,而其配置覆蓋的形式,則是使用的Spring Boot 的 AutoConfiguration 機制實現(xiàn)的
如:若開啟feign.okhttp.enabled=true,則okhttp的超時時間是feign.httpclient.connectionTimeout的值,默認2000毫秒
總結(jié):超時——還是 feign 說了算!
四、hystrix dashboard
能夠?qū)⑦@些狀態(tài)可視化,是非常棒的,需要引入一個jar包。
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
- </dependency>
下面這張圖,就是針對后臺監(jiān)控的一些解釋。
(圖片來自網(wǎng)絡(luò))
附:配置參數(shù)說明
一、Command Properties
以下屬性控制HystrixCommand,前綴hystrix.command.default
1、Execution
以下屬性控制HystrixCommand.run()如何執(zhí)行。
比較重要的參數(shù),有:
execution.isolation.strategy
execution.isolation.thread.timeoutInMilliseconds
2、Fallback
以下屬性控制HystrixCommand.getFallback()如何執(zhí)行。這些屬性適用于ExecutionIsolationStrategy.THREAD和ExecutionIsolationStrategy.SEMAPHORE。
3、Circuit Breaker
斷路器屬性控制HystrixCircuitBreaker。
4、Metrics
以下屬性與從HystrixCommand和HystrixObservableCommand執(zhí)行捕獲指標有關(guān)。
5、Request Context
這些屬性涉及HystrixCommand使用的HystrixRequestContext功能
二、Command Properties
下列屬性控制HystrixCollapser行為。前綴:hystrix.collapser.default
三、ThreadPool Properties
以下屬性控制Hystrix命令在其上執(zhí)行的線程池的行為。
大多數(shù)時候,默認值為10的線程會很好(通常可以做得更小)前綴:hystrix.threadpool.default 。
