1 隔離政策 - ExecutionIsolationStrategy
執行HystrixCommand時使用
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iMhlzMlJjMiVmMhF2MzIWYiZGZ0MmY5EWNhhDOjFGMx8CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.png)
指定HystrixCommand.run()的資源隔離政策。
資源隔離,要解決的最核心的問題,就是将多個依賴服務的調用分别隔離到各自資源池内。避免對某個依賴服務的調用,因為依賴服務的接口調用的延遲或者失敗,導緻服務所有線程資源全部耗費在該服務的接口調用上。
1.1 THREAD - 線程池隔離
線程池隔離技術,并非指控制類似tomcat web容器的線程。嚴格意義說,hystrix的線程池隔離技
術,控制tomcat線程的執行。線程池滿後,確定tomcat的線程不會因為依賴服務的接口調用延遲或故障,被hang住,fallback , ms。tomcat其他的線程不會卡死,快速傳回,然後可以支撐其他的事情。
線程池和信号量做資源隔離、限流、容量的限制,預設的容量都是10。
線程池隔離技術是用自己的線程去執行調用的。
信号量隔離技術,是直接讓tomcat的線程去調用依賴服務的。
預設的政策為線程池。
THREAD:在單獨的線程上執行HystrixCommand#run方法,使用線程池大小限制并發
基于線程池
HystrixCommandProperties.Setter()
.withExecutionIsolationStrategy(ExecutionIsolationStrategy.THREAD)
優點
支援排隊和逾時
支援異步調用
不足
線程調用會産生額外的性能開銷。
容易由于建立大量線程而 OOM,是以 sentinel 隻支援信号量隔離。
适用場景
适合絕大多數的場景,線程池,對依賴服務的網絡請求的調用和通路,逾時這種問題。
不受信客戶
有限扇出
1.2 SEMAPHORE - 信号量隔離
SEMAPHORE:在調用線程上執行HystrixCommand#run方法,使用信号量許可計數限制
基于信号量
HystrixCommandProperties.Setter()
.withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)
線程池機制,每個command運作在一個線程中,限流是通過線程池的大小來控制的
信号量機制,command是運作在調用線程中,但是通過信号量的容量來進行限流
輕量,無額外開銷。
不支援任務排隊和主動逾時
不支援異步調用
适合通路不是對外部依賴的通路,而是對内部比較複雜業務邏輯的通路。
但像這種通路,系統内部代碼,其實不涉及任何的網絡請求,那麼隻要做信号量的普通限流即可。
因為不需要去捕獲類似逾時的問題,算法效率要求不是太高。并發量突然太高,因為這裡稍微耗時一些,導緻很多線程卡在這裡的話,不太好,是以進行一個基本的資源隔離和通路,避免内部複雜的低效率代碼,導緻大量線程夯死。
受信客戶
高扇出(網關)
高頻高速調用
使用信号量場景,通常是針對超大并發量,每個服務執行個體每秒都幾百QPS。
此時如果用線程池,線程一般不會太多,可能撐不住高并發。要撐住,可能要耗費大量線程資源,那麼就用信号量,來限流保護。
一般用信号量常見于那種基于純記憶體服務,而不涉及到任何網絡通路請求。
netflix有100+的command運作在40+的線程池中,隻有少數command是不運作線上程池中的,就是從純記憶體中擷取一些中繼資料,或者是對多個command包裝起來的facacde command,是用信号量限流的。
比如緩存服務,可能會将部分量特别少,通路又特别頻繁的一些資料,放在純記憶體。
一般我們在擷取到商品資料之後,都要去擷取商品是屬于哪個地理位置,省,市,賣家的
可能在自己的純記憶體中,比如就一個Map去擷取。對于這種直接通路本地記憶體的邏輯,比較适合用信号量做一下簡單的隔離。
優點在于,不用自己管理線程池,不用擔心逾時,信号量做隔離的話,性能會相對高。
坑點
2 command名稱 & command組
2.1 command名稱
每個command,都可設定自己的名稱,同時可以設定一個自己的組。
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;
}
2.2 command group
預設情況下,因為就是通過command group來定義一個線程池,而且還會通過command group聚合一些監控和報警資訊。
同一command group中的請求,都會進入同一個線程池中。