怎么通過 Hystrix 執行緒池技術實作資源隔離?
資源隔離,就是說,你如果要把對某一個依賴服務的所有呼叫請求,全部隔離在同一份資源池內,不會去用其它資源了,這就叫資源隔離,哪怕對這個依賴服務,比如說商品服務,現在同時發起的呼叫量已經到了 1000,但是執行緒池內就 10 個執行緒,最多就只會用這 10 個執行緒去執行,不會說,對商品服務的請求,因為介面呼叫延時,將 tomcat 內部所有的執行緒資源全部耗盡,
Hystrix 進行資源隔離,其實是提供了一個抽象,叫做 command,這也是 Hystrix 最最基本的資源隔離技術,
一、利用 HystrixCommand 獲取單條資料
我們通過將呼叫商品服務的操作封裝在 HystrixCommand 中,限定一個 key,比如下面的 GetProductInfoCommandGroup,在這里我們可以簡單認為這是一個執行緒池,每次呼叫商品服務,就只會用該執行緒池中的資源,不會再去用其它執行緒資源了,
public class GetProductInfoCommand extends HystrixCommand<ProductInfo> {
private Long productId;
public GetProductInfoCommand(Long productId) {
super(HystrixCommandGroupKey.Factory.asKey("GetProductInfoCommandGroup"));
this.productId = productId;
}
@Override
protected ProductInfo run() {
String url = "http://localhost:8081/getProductInfo?productId=" + productId;
// 呼叫商品服務介面
String response = HttpClientUtils.sendGetRequest(url);
return JSONObject.parseObject(response, ProductInfo.class);
}
}
我們在快取服務介面中,根據 productId 創建 command 并執行,獲取到商品資料,
@RequestMapping("/getProductInfo")
@ResponseBody
public String getProductInfo(Long productId) {
HystrixCommand<ProductInfo> getProductInfoCommand = new GetProductInfoCommand(productId);
// 通過 command 執行,獲取最新商品資料
ProductInfo productInfo = getProductInfoCommand.execute();
System.out.println(productInfo); return "success";
}
上面執行的是 execute() 方法,其實是同步的,也可以對 command 呼叫 queue() 方法,它僅僅是將 command 放入執行緒池的一個等待佇列,就立即回傳,拿到一個 Future 物件,后面可以繼續做其它一些事情,然后過一段時間對 Future 呼叫 get() 方法獲取資料,這是異步的,
二、利用 HystrixObservableCommand 批量獲取資料
只要是獲取商品資料,全部都系結到同一個執行緒池里面去,我們通過 HystrixObservableCommand 的一個執行緒去執行,而在這個執行緒里面,批量把多個 productId 的 productInfo 拉回來,
public class GetProductInfosCommand extends HystrixObservableCommand<ProductInfo> {
private String[] productIds;
public GetProductInfosCommand(String[] productIds) {
// 還是系結在同一個執行緒池
super(HystrixCommandGroupKey.Factory.asKey("GetProductInfoGroup"));
this.productIds = productIds;
}
@Override
protected Observable<ProductInfo> construct() {
return Observable.unsafeCreate((Observable.OnSubscribe<ProductInfo>) subscriber -> {
for (String productId : productIds) {
// 批量獲取商品資料
String url = "http://localhost:8081/getProductInfo?productId=" + productId;
String response = HttpClientUtils.sendGetRequest(url);
ProductInfo productInfo = JSONObject.parseObject(response, ProductInfo.class);
subscriber.onNext(productInfo);
}subscriber.onCompleted();
}).subscribeOn(Schedulers.io());
}
}
在快取服務介面中,根據傳來的 id 串列,比如是以 ,分隔的 id 串,通過上面的 HystrixObservableCommand,執行 Hystrix 的一些 API 方法,獲取到所有商品資料,
public String getProductInfos(String productIds) {
String[] productIdArray = productIds.split(",");
HystrixObservableCommand<ProductInfo> getProductInfosCommand = new GetProductInfosCommand(productIdArray);
Observable<ProductInfo> observable = getProductInfosCommand.observe();
observable.subscribe(new Observer<ProductInfo>() {
@Override
public void onCompleted() {
System.out.println("獲取完了所有的商品資料");
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
/**
* 獲取完一條資料,就回呼一次這個方法
* @param productInfo
*/
@Override
public void onNext(ProductInfo productInfo) {
System.out.println(productInfo);
}
}); return "success";
}
我們回過頭來,看看 Hystrix 執行緒池技術是如何實作資源隔離的,

從 Nginx 開始,快取都失效了,那么 Nginx 通過快取服務去呼叫商品服務,快取服務默認的執行緒大小是 10 個,最多就只有 10 個執行緒去呼叫商品服務的介面,即使商品服務介面故障了,最多就只有 10 個執行緒會 hang 死在呼叫商品服務介面的路上,快取服務的 tomcat 內其它的執行緒還是可以用來呼叫其它的服務,干其它的事情,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/277493.html
標籤:其他
上一篇:智能化運維筆記【1】
