Java高階架構面試知識點整理:基於 Hystrix 執行緒池技術實現資源隔離

無敵天驕發表於2021-04-17

怎麼透過 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 = "
         
        // 呼叫商品服務介面 
        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 = " 
                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 執行緒池技術是如何實現資源隔離的。

Java高階架構面試知識點整理:基於 Hystrix 執行緒池技術實現資源隔離













從 Nginx 開始,快取都失效了,那麼 Nginx 透過快取服務去呼叫商品服務。快取服務預設的執行緒大小是 10 個,最多就只有 10 個執行緒去呼叫商品服務的介面。即使商品服務介面故障了,最多就只有 10 個執行緒會 hang 死在呼叫商品服務介面的路上,快取服務的 tomcat 內其它的執行緒還是可以用來呼叫其它的服務,幹其它的事情。

喜歡這篇文章的朋友們可以關注個人簡介中的公眾號

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69964492/viewspace-2768556/,如需轉載,請註明出處,否則將追究法律責任。

相關文章