Hystrix - 資源隔離模式 (線程池模式+信號量模式)


總結

1. 線程池模式 vs 信號量模式

 

  線程池隔離 信號量隔離
線程 與調用線程非相同線程 與調用線程相同(tomcat/jetty線程)
開銷 排隊、調度、上下文開銷等 無線程切換,開銷低
異步 可以是異步,也可以是同步。看調用的方法 同步調用,不支持異步
並發支持 支持(最大線程池大小hystrix.threadpool.default.maximumSize) 支持(最大信號量上限maxConcurrentRequests)  
是否超時  支持,可直接返回 不支持,如果阻塞,只能通過調用協議(如:socket超時才能返回)
是否支持熔斷

支持,當線程池到達maxSize后,並且工作隊列也滿,再請求會觸發fallback接口進行熔斷

支持,當信號量達到maxConcurrentRequests后。再請求會觸發fallback
隔離原理 每個服務單獨用線程池 通過信號量的計數器
資源開銷   大,大量線程的上下文切換,容易造成機器負載高 小,只是個計數器 
使用場景 當請求的服務網絡開銷比較大的時候,或者是請求比較耗時的時候。為了保證可以大量的容器(tomcat)線程可用,不會由於服務原因,一直處於阻塞或等待狀態,會pick this 當請求不耗時,返回通常很快,不會占用容器線程太長的時間;pick this 同時也減少了線程切換的開銷。

 

下圖的左邊2/3是線程池資源隔離示意圖,右邊的1/3是信號量資源隔離示意圖,我們先來看左邊的示意圖。

 

 

我們先來看左邊的示意圖。

當用戶請求服務A和服務I的時候,tomcat的線程(圖中藍色箭頭標注)會將請求的任務交給服務A和服務I的內部線程池里面的線程(圖中橘色箭頭標注)來執行,tomcat的線程就可以去干別的事情去了,當服務A和服務I自己線程池里面的線程執行完任務之后,就會將調用的結果返回給tomcat的線程,從而實現資源的隔離,當有大量並發的時候,服務內部的線程池的數量就決定了整個服務的並發度,例如服務A的線程池大小為10個,當同時有12請求時,只會允許10個任務在執行,其他的任務被放在線程池隊列中,或者是直接走降級服務,此時,如果服務A掛了,就不會造成大量的tomcat線程被服務A拖死,服務I依然能夠提供服務。整個系統不會受太大的影響。

 

線程池模式的優缺點

優點:

  • 一個依賴可以給予一個線程池,這個依賴的異常不會影響其他的依賴。
  • 使用線程池模式可以完全隔離第三方代碼,請求線程(客戶端的線程)可以快速放回。
  • 當一個失敗的依賴再次變成可用時,線程池將清理,並立即恢復可用,而不是一個長時間的恢復。
  • 可以完全模擬異步調用,方便異步編程。
  • 使用線程池,可以有效的進行實時監控、統計和封裝。

缺點:

  • 使用線程池的缺點主要是增加了計算的開銷。每一個依賴調用都會涉及到隊列,調度,上下文切換,而這些操作都有可能在不同的線程中執行。
  • Netflix 更偏向於使用線程池來隔離依賴服務,因為經過計算,線程切換的消耗在可接受范圍之內。並且能支持包括超時在內的所有功能。

 

2. 設置隔離模式:線程池/信號量

execution.isolation.strategy: "THREAD"/"SEMAPHORE"

@HystrixCommand(
        commandProperties = { //利用commandProperties更改線程池的一些默認配置
            //選擇“線程池”模式、"信號量"模式
            @HystrixProperty(name="execution.isolation.strategy",value = "THREAD"/"SEMAPHORE"), 
            //超時
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000"),
            //信號量大小為10,那么同時只允許10個tomcat的線程(此處是tomcat的線程,而不是服務的獨立線程池里面的線程)來訪問服務,其他的請求就會被拒絕,從而達到限流保護的作用
            @HystrixProperty(name="execution.isolation.semaphore.maxConcurrentRequests",value = "10"),
        },
)
public List<License> getLicensesByOrg(String organizationId){
    //....
}

 

 

3. 設置隔離線程池、線程數量、隊列長度、fallback方法

默認情況下,Hystrix不做線程隔離,因此容易造成服務雪崩...

如果想設置隔離線程池,需要:

@HystrixCommand(
        //設置一個隔離的線程池
        threadPoolKey = "licenseByOrgThreadPool",
        threadPoolProperties = {
            //設置該線程池的線程數
            @HystrixProperty(name = "coreSize",value="30"),
            //設置隊列的容量,該隊列的作用是當線程池中的線程都處於工作狀態,接下來的請求會進入該隊列
            @HystrixProperty(name="maxQueueSize", value="10")
        }
        //一旦隊列中也滿了,再來的請求就執行“服務降級”fallback方法
        fallbackMethod = "buildFallbackLicenseList"
)
public List<License> getLicensesByOrg(String organizationId){
    //...
}

 

 

參考文獻

服務容錯保護斷路器Hystrix之八:Hystrix資源隔離策略

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM