Tungsten Fabric SDN — SmartNIC vRouter
908
2025-03-31
1 隔離策略 - ExecutionIsolationStrategy
執(zhí)行HystrixCommand時(shí)使用
指定HystrixCommand.run()的資源隔離策略。
資源隔離,要解決的最核心的問題,就是將多個(gè)依賴服務(wù)的調(diào)用分別隔離到各自資源池內(nèi)。避免對某個(gè)依賴服務(wù)的調(diào)用,因?yàn)橐蕾嚪?wù)的接口調(diào)用的延遲或者失敗,導(dǎo)致服務(wù)所有線程資源全部耗費(fèi)在該服務(wù)的接口調(diào)用上。
1.1 THREAD - 線程池隔離
線程池隔離技術(shù),并非指控制類似tomcat web容器的線程。嚴(yán)格意義說,hystrix的線程池隔離技
術(shù),控制tomcat線程的執(zhí)行。線程池滿后,確保tomcat的線程不會因?yàn)橐蕾嚪?wù)的接口調(diào)用延遲或故障,被hang住,fallback , ms。tomcat其他的線程不會卡死,快速返回,然后可以支撐其他的事情。
線程池和信號量做資源隔離、限流、容量的限制,默認(rèn)的容量都是10。
線程池隔離技術(shù)是用自己的線程去執(zhí)行調(diào)用的。
信號量隔離技術(shù),是直接讓tomcat的線程去調(diào)用依賴服務(wù)的。
默認(rèn)的策略為線程池。
THREAD:在單獨(dú)的線程上執(zhí)行HystrixCommand#run方法,使用線程池大小限制并發(fā)
基于線程池
HystrixCommandProperties.Setter() .withExecutionIsolationStrategy(ExecutionIsolationStrategy.THREAD)
1
2
優(yōu)點(diǎn)
支持排隊(duì)和超時(shí)
支持異步調(diào)用
不足
線程調(diào)用會產(chǎn)生額外的性能開銷。
容易由于創(chuàng)建大量線程而 OOM,所以 sentinel 只支持信號量隔離。
適用場景
適合絕大多數(shù)的場景,線程池,對依賴服務(wù)的網(wǎng)絡(luò)請求的調(diào)用和訪問,超時(shí)這種問題。
不受信客戶
有限扇出
1.2 SEMAPHORE - 信號量隔離
SEMAPHORE:在調(diào)用線程上執(zhí)行HystrixCommand#run方法,使用信號量許可計(jì)數(shù)限制
基于信號量
HystrixCommandProperties.Setter() .withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)
1
2
線程池機(jī)制,每個(gè)command運(yùn)行在一個(gè)線程中,限流是通過線程池的大小來控制的
信號量機(jī)制,command是運(yùn)行在調(diào)用線程中,但是通過信號量的容量來進(jìn)行限流
優(yōu)點(diǎn)
輕量,無額外開銷。
不足
不支持任務(wù)排隊(duì)和主動(dòng)超時(shí)
不支持異步調(diào)用
適用場景
適合訪問不是對外部依賴的訪問,而是對內(nèi)部比較復(fù)雜業(yè)務(wù)邏輯的訪問。
但像這種訪問,系統(tǒng)內(nèi)部代碼,其實(shí)不涉及任何的網(wǎng)絡(luò)請求,那么只要做信號量的普通限流即可。
因?yàn)椴恍枰ゲ东@類似超時(shí)的問題,算法效率要求不是太高。并發(fā)量突然太高,因?yàn)檫@里稍微耗時(shí)一些,導(dǎo)致很多線程卡在這里的話,不太好,所以進(jìn)行一個(gè)基本的資源隔離和訪問,避免內(nèi)部復(fù)雜的低效率代碼,導(dǎo)致大量線程夯死。
受信客戶
高扇出(網(wǎng)關(guān))
高頻高速調(diào)用
使用信號量場景,通常是針對超大并發(fā)量,每個(gè)服務(wù)實(shí)例每秒都幾百Q(mào)PS。
此時(shí)如果用線程池,線程一般不會太多,可能撐不住高并發(fā)。要撐住,可能要耗費(fèi)大量線程資源,那么就用信號量,來限流保護(hù)。
一般用信號量常見于那種基于純內(nèi)存服務(wù),而不涉及到任何網(wǎng)絡(luò)訪問請求。
netflix有100+的command運(yùn)行在40+的線程池中,只有少數(shù)command是不運(yùn)行在線程池中的,就是從純內(nèi)存中獲取一些元數(shù)據(jù),或者是對多個(gè)command包裝起來的facacde command,是用信號量限流的。
比如緩存服務(wù),可能會將部分量特別少,訪問又特別頻繁的一些數(shù)據(jù),放在純內(nèi)存。
一般我們在獲取到商品數(shù)據(jù)之后,都要去獲取商品是屬于哪個(gè)地理位置,省,市,賣家的
可能在自己的純內(nèi)存中,比如就一個(gè)Map去獲取。對于這種直接訪問本地內(nèi)存的邏輯,比較適合用信號量做一下簡單的隔離。
優(yōu)點(diǎn)在于,不用自己管理線程池,不用擔(dān)心超時(shí),信號量做隔離的話,性能會相對高。
坑點(diǎn)
2 command名稱 & command組
2.1 command名稱
每個(gè)command,都可設(shè)置自己的名稱,同時(shí)可以設(shè)置一個(gè)自己的組。
private static final Setter cachedSetter = Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")) .andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld")); public CommandHelloWorld(String name) { super(cachedSetter); this.name = name; }
1
2
3
4
5
6
7
8
2.2 command group
默認(rèn)情況下,因?yàn)榫褪峭ㄟ^command group來定義一個(gè)線程池,而且還會通過command group聚合一些監(jiān)控和報(bào)警信息。
同一command group中的請求,都會進(jìn)入同一個(gè)線程池中。
3 command線程池
ThreadPoolKey代表了一個(gè)HystrixThreadPool,用來進(jìn)行統(tǒng)一監(jiān)控,統(tǒng)計(jì),緩存
默認(rèn)的threadpool key就是command group名稱
每個(gè)command都會跟它的ThreadPoolKey對應(yīng)的ThreadPool綁定
如果不想直接用command group,也可以手動(dòng)設(shè)置thread pool name
public CommandHelloWorld(String name) { super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")) .andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld")) .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("HelloWorldPool"))); this.name = name; }
1
2
3
4
5
6
command threadpool => command group => command key
command key
代表了一類command,代表底層的依賴服務(wù)的一個(gè)接口
command group
代表了某一個(gè)底層的依賴服務(wù),合理,一個(gè)依賴服務(wù)可能會暴露出來多個(gè)接口,每個(gè)接口就是一個(gè)command key
command group
在邏輯上去組織起來一堆command key的調(diào)用,統(tǒng)計(jì)信息,成功次數(shù),timeout超時(shí)次數(shù),失敗次數(shù),可以看到某一個(gè)服務(wù)整體的一些訪問情況
推薦是根據(jù)一個(gè)服務(wù)去劃分出一個(gè)線程池,command key默認(rèn)都是屬于同一個(gè)線程池的
比如說你以一個(gè)服務(wù)為粒度,估算出來這個(gè)服務(wù)每秒的所有接口加起來的整體QPS在100左右
你調(diào)用那個(gè)服務(wù)的當(dāng)前服務(wù),部署了10個(gè)服務(wù)實(shí)例,每個(gè)服務(wù)實(shí)例上,其實(shí)用這個(gè)command group對應(yīng)這個(gè)服務(wù),給一個(gè)線程池,量大概在10個(gè)左右,就可以了,你對整個(gè)服務(wù)的整體的訪問QPS大概在每秒100左右
一般來說,command group是用來在邏輯上組合一堆command的
舉個(gè)例子,對于一個(gè)服務(wù)中的某個(gè)功能模塊來說,希望將這個(gè)功能模塊內(nèi)的所有command放在一個(gè)group中,那么在監(jiān)控和報(bào)警的時(shí)候可以放一起看
command group,對應(yīng)了一個(gè)服務(wù),但是這個(gè)服務(wù)暴露出來的幾個(gè)接口,訪問量很不一樣,差異非常之大
你可能就希望在這個(gè)服務(wù)command group內(nèi)部,包含的對應(yīng)多個(gè)接口的command key,做一些細(xì)粒度的資源隔離
對同一個(gè)服務(wù)的不同接口,都使用不同的線程池
command key -> command group command key -> 自己的threadpool key
1
2
3
邏輯上來說,多個(gè)command key屬于一個(gè)command group,在做統(tǒng)計(jì)的時(shí)候,會放在一起統(tǒng)計(jì)
每個(gè)command key有自己的線程池,每個(gè)接口有自己的線程池,去做資源隔離和限流
但對于thread pool資源隔離來說,可能是希望能夠拆分的更加一致一些,比如在一個(gè)功能模塊內(nèi),對不同的請求可以使用不同的thread pool
command group一般來說,可以是對應(yīng)一個(gè)服務(wù),多個(gè)command key對應(yīng)這個(gè)服務(wù)的多個(gè)接口,多個(gè)接口的調(diào)用共享同一個(gè)線程池
如果說你的command key,要用自己的線程池,可以定義自己的threadpool key,就ok了
4 coreSize
設(shè)置線程池的大小,默認(rèn)是10
HystrixThreadPoolProperties.Setter() .withCoreSize(int value)
1
2
一般來說,用這個(gè)默認(rèn)的10個(gè)線程大小就夠了
5 queueSizeRejectionThreshold
控制queue滿后reject的threshold,因?yàn)閙axQueueSize不允許熱修改,因此提供這個(gè)參數(shù)可以熱修改,控制隊(duì)列的最大值
HystrixCommand在提交到線程池之前,其實(shí)會先進(jìn)入一個(gè)隊(duì)列中,這個(gè)隊(duì)列滿了之后,才會reject
默認(rèn)值是5
HystrixThreadPoolProperties.Setter() .withQueueSizeRejectionThreshold(int value)
1
2
線程池+queue的工作原理
6 isolation.semaphore.maxConcurrentRequests
設(shè)置使用SEMAPHORE隔離策略的時(shí)候,允許訪問的最大并發(fā)量,超過這個(gè)最大并發(fā)量,請求直接被reject
這個(gè)并發(fā)量的設(shè)置,跟線程池大小的設(shè)置,應(yīng)該是類似的
但是基于信號量的話,性能會好很多,而且hystrix框架本身的開銷會小很多
默認(rèn)值是10,設(shè)置的小一些,否則因?yàn)樾盘柫渴腔谡{(diào)用線程去執(zhí)行command的,而且不能從timeout中抽離,因此一旦設(shè)置的太大,而且有延時(shí)發(fā)生,可能瞬間導(dǎo)致tomcat本身的線程資源本占滿
Tomcat 任務(wù)調(diào)度
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。