Hystrix- 基於 Hystrix 訊號量機制實現資源隔離
基於 Hystrix 訊號量機制實現資源隔離
Hystrix 裡面核心的一項功能,其實就是所謂的資源隔離,要解決的最最核心的問題,就是將多個依賴服務的呼叫分別隔離到各自的資源池內。避免說對某一個依賴服務的呼叫,因為依賴服務的介面呼叫的延遲或者失敗,導致服務所有的執行緒資源全部耗費在這個服務的介面呼叫上。一旦說某個服務的執行緒資源全部耗盡的話,就可能導致服務崩潰,甚至說這種故障會不斷蔓延。
Hystrix 實現資源隔離,主要有兩種技術:
- 執行緒池
- 訊號量
預設情況下,Hystrix 使用執行緒池模式。
前面已經說過執行緒池技術了,這一小節就來說說訊號量機制實現資源隔離,以及這兩種技術的區別與具體應用場景。
訊號量機制
訊號量的資源隔離只是起到一個開關的作用,比如,服務 A 的訊號量大小為 10,那麼就是說它同時只允許有 10 個 tomcat 執行緒來訪問服務 A,其它的請求都會被拒絕,從而達到資源隔離和限流保護的作用。
執行緒池與訊號量區別
執行緒池隔離技術,並不是說去控制類似 tomcat 這種 web 容器的執行緒。更加嚴格的意義上來說,Hystrix 的執行緒池隔離技術,控制的是 tomcat 執行緒的執行。Hystrix 執行緒池滿後,會確保說,tomcat 的執行緒不會因為依賴服務的介面呼叫延遲或故障而被 hang 住,tomcat 其它的執行緒不會卡死,可以快速返回,然後支撐其它的事情。
執行緒池隔離技術,是用 Hystrix 自己的執行緒去執行呼叫;而訊號量隔離技術,是直接讓 tomcat 執行緒去呼叫依賴服務。訊號量隔離,只是一道關卡,訊號量有多少,就允許多少個 tomcat 執行緒通過它,然後去執行。
適用場景:
- 執行緒池技術,適合絕大多數場景,比如說我們對依賴服務的網路請求的呼叫和訪問、需要對呼叫的 timeout 進行控制(捕捉 timeout 超時異常)。
- 訊號量技術,適合說你的訪問不是對外部依賴的訪問,而是對內部的一些比較複雜的業務邏輯的訪問,並且系統內部的程式碼,其實不涉及任何的網路請求,那麼只要做訊號量的普通限流就可以了,因為不需要去捕獲 timeout 類似的問題。
訊號量簡單 Demo
業務背景裡,比較適合訊號量的是什麼場景呢?
比如說,我們一般來說,快取服務,可能會將一些量特別少、訪問又特別頻繁的資料,放在自己的純記憶體中。
舉個例子。一般我們在獲取到商品資料之後,都要去獲取商品是屬於哪個地理位置、省、市、賣家等,可能在自己的純記憶體中,比如就一個 Map 去獲取。對於這種直接訪問本地記憶體的邏輯,比較適合用訊號量做一下簡單的隔離。
優點在於,不用自己管理執行緒池啦,不用 care timeout 超時啦,也不需要進行執行緒的上下文切換啦。訊號量做隔離的話,效能相對來說會高一些。
假如這是本地快取,我們可以通過 cityId,拿到 cityName。
public class LocationCache {
private static Map<Long, String> cityMap = new HashMap<>();
static {
cityMap.put(1L, "北京");
}
/**
* 通過cityId 獲取 cityName
*
* @param cityId 城市id
* @return 城市名
*/
public static String getCityName(Long cityId) {
return cityMap.get(cityId);
}
}
寫一個 GetCityNameCommand,策略設定為訊號量。run() 方法中獲取本地快取。我們目的就是對獲取本地快取的程式碼進行資源隔離。
public class GetCityNameCommand extends HystrixCommand<String> {
private Long cityId;
public GetCityNameCommand(Long cityId) {
// 設定訊號量隔離策略
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GetCityNameGroup"))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)));
this.cityId = cityId;
}
@Override
protected String run() {
// 需要進行訊號量隔離的程式碼
return LocationCache.getCityName(cityId);
}
}
在介面層,通過建立 GetCityNameCommand,傳入 cityId,執行 execute() 方法,那麼獲取本地 cityName 快取的程式碼將會進行訊號量的資源隔離。
@RequestMapping("/getProductInfo")
@ResponseBody
public String getProductInfo(Long productId) {
HystrixCommand<ProductInfo> getProductInfoCommand = new GetProductInfoCommand(productId);
// 通過command執行,獲取最新商品資料
ProductInfo productInfo = getProductInfoCommand.execute();
Long cityId = productInfo.getCityId();
GetCityNameCommand getCityNameCommand = new GetCityNameCommand(cityId);
// 獲取本地記憶體(cityName)的程式碼會被訊號量進行資源隔離
String cityName = getCityNameCommand.execute();
productInfo.setCityName(cityName);
System.out.println(productInfo);
return "success";
}
轉載自:網際網路 Java 工程師進階知識完全掃盲,萬分感謝。
更多資訊,關注java架構
相關文章
- Java高階架構面試知識點:基於 Hystrix 訊號量機制實現資源隔離Java架構面試
- Java高階架構面試知識點整理:基於 Hystrix 執行緒池技術實現資源隔離Java架構面試執行緒
- 基於hadoop_yarn的資源隔離配置HadoopYarn
- Yarn資源隔離Yarn
- qiankun 的 CSS 沙箱隔離機制CSS
- qiankun 的 JS 沙箱隔離機制JS
- mysql 事務,鎖,隔離機制MySql
- 資源隔離技術之記憶體隔離記憶體
- 「分散式技術專題」事務型、分析型資料資源隔離機制分散式
- 容器的工作原理和隔離機制
- [java併發程式設計]基於訊號量semaphore實現限流器Java程式設計
- 如何實現css隔離?CSS
- 從零開始寫 Docker(五)---基於 overlayfs 實現寫操作隔離Docker
- 程式間通訊——基於共享記憶體和訊號量實現共享佇列記憶體佇列
- Java如何實現消費資料隔離?Java
- 事務隔離(二):基於加鎖方式的事務隔離原理
- Hystrix 自動降級與依賴隔離原理
- linux 訊號機制Linux
- PostgreSQL 併發控制機制(1):隔離級別SQL
- Mysql事務隔離級別與鎖機制MySql
- Hystrix超時機制
- 基於公共信箱的全量訊息實現
- egg基於jsonwebtoken的Token實現認證機制JSONWeb
- Laravel基於reset機制實現分散式事務Laravel分散式
- Linux中訊號量的實現Linux
- eBPF Cilium實戰(1) - 基於團隊的網路隔離eBPF
- MySQL是如何實現事物隔離?MySql
- hystrix執行緒池隔離的原理與驗證執行緒
- 2.3.2 訊號量機制——作業系統筆記作業系統筆記
- MySQL資料庫事務隔離性的實現MySql資料庫
- Spark SQL外部資料來源與實現機制SparkSQL
- 建立程序,設計訊號量同步機制,實現多執行緒同步 - C語言版執行緒C語言
- 微服務熔斷隔離機制及注意事項微服務
- 混部之殤-論雲原生資源隔離技術之CPU隔離(一)
- Linux訊號(signal)機制Linux
- Semaphore-訊號量的實現分析
- Hystrix semaphore和thread隔離策略的區別及配置參thread
- 基於TimeLine模型的訊息同步機制模型