插上NIO的翅膀,FunTester飛上天

在前段時間對性能測試框架對比的文章中,我又重新學習了Java NIO知識的學習,又發掘了一項「FunTester」優化,說幹就幹,現在就行動起來。

首先呢,先複習一下關於統計QPS中用到到一個請求模型。在之前的兩篇討論性能測試誤差的文章性能測試誤差分析文字版-上性能測試誤差分析文字版-下中,我畫了一個簡單的請求時間模型。

計算模型

如圖所示,這是單個線程單個請求的耗時簡易模型,分成三部分:請求前(對應before)、請求與響應(對應request and response)和請求後(對應after)。其中T代表三個部分的總時間,rt代表了請求與響應的時間。

請求計算模型

Java NIO

Java NIO有兩種解釋:一種叫非阻塞IO(Non-blocking I/O),另一種也叫新的IO(New I/O),其實是同一個概念。NIO是一種基於通道和緩衝區的I/O方式,它可以使用Native函數庫直接分配堆外內存(區別於JVM的運行時數據區),然後通過一個存儲在java堆裏面的DirectByteBuffer對象作爲這塊內存的直接引用進行操作。這樣能在一些場景顯著提高性能,因爲避免了在Java堆和Native堆中來回複製數據。

以上內容摘要,我的理解也不十分透徹。PS:我更建議有能力的搜一搜,瞭解一下也是好的。

下面我分享一下Java NIOHTTP協議接口測試中的應用。

緣由

在上圖第二部分中,請求和響應占據了整個部分。如果我們將這部分再細分,那麼可以分成三個部分:發出請求、等待響應、接收響應。Java NIO在接口測試中的應用就在等待響應和接收響應這一部分。如果我們使用一種技術,將發出請求之後,等待響應和接收響應這個過程交給另外線程處理,又不影響兩者之間的關係,那麼我們就可以不斷地發出請求,提高客戶端性能而又不影響我們接收響應,進行業務驗證。

對於那些響應時間比較長的接口來說。這樣的處理結果能夠極大的提升客戶端發送請求的速率。對於線程數一定的情況下,由單個客戶端發起的壓力也會成倍的增加。經過本人在本地進行單線程模擬測試。(這個倍數大約在30倍左右。可見Java NIO的性能提升有多強。當然在實際的更大壓力的性能測試中,這個倍數會降低很多。)

HttpClient應用

HttpAsyncClient則使用Java NIO的異步非阻塞事件驅動I/O模型,實現了真正意義的異步調用,使用HttpAsyncClient我們需要引入其專門的包

之前我有寫過文章:HTTP異步連接池和多線程實踐,只不過現在在看當時顯得特別的字呢,對於http client異步客戶端也有點兒理解不透徹,特別是對於callback函數的應用。

核心方法如下:

    @Override
    public Future<HttpResponse> execute(
            final HttpUriRequest request,
            final FutureCallback<HttpResponse> callback)
 
{
        return execute(request, HttpClientContext.create(), callback);
    }

第一個是參數請求對象,第二個參數是回調函數。其中我之前常用的請求對象org.apache.http.client.methods.HttpRequestBase,具體實現代碼摘要public abstract class HttpRequestBase extends AbstractExecutionAwareRequest implements HttpUriRequest, Configurable

下面是我經過一些資料的查證,重新寫了一下。Http client異步客戶端的使用方法的封裝。

不管不顧

這個方法只負責把請求發出去,至於響應一律不管。這裏據我查證,callback如果傳null的話,在處理響應的時候會直接釋放連接等相關資源。

    /**
     * 異步發送請求
     *
     * @param request
     */

    public static void executeSync(HttpRequestBase request) {
        ClientManage.httpAsyncClient.execute(request, null);
    }

異步打印日誌

通過一個簡單的日誌打印功能實現FutureCallback,來實現異步響應結果的解析和日誌打印功能。

    /**
     * 異步請求,打印日誌
     *
     * @param request
     * @param response
     */

    public static void executeSyncWithLog(HttpRequestBase request) {
        ClientManage.httpAsyncClient.execute(request, logCallback);
    }


    /**
     * 異步請求打印日誌的callback
     */

    public static final FutureCallback<HttpResponse> logCallback = new FutureCallback<HttpResponse>() {
        @Override
        public void completed(HttpResponse httpResponse) {
            HttpEntity entity = httpResponse.getEntity();
            String content = getContent(entity);
            logger.info("響應結果:{}", content);
        }

        @Override
        public void failed(Exception e) {
            logger.warn("響應失敗", e);
        }

        @Override
        public void cancelled() {
            logger.warn("取消執行");
        }
    };

異步解析響應

這裏我引入了第二個參數com.alibaba.fastjson.JSONObject,用來保存解析響應,之所以加上這個,用來異步保存響應結果,用來業務驗證。


    /**
     * 異步請求,返回響應,引入第二個參數{@link JSONObject}
     *
     * @param request
     * @param response
     */

    public static void executeSyncWithResponse(HttpRequestBase request, JSONObject response) {
        ClientManage.httpAsyncClient.execute(request, new FunTester(response));
    }


    /**
     * 異步請求,異步解析響應的FutureCallback實現類
     */

   private static class FunTester implements FutureCallback<HttpResponse{

        public FunTester(JSONObject response) {
            this.response = response;
        }

        JSONObject response;

        @Override
        public void completed(HttpResponse result) {
            HttpEntity entity = result.getEntity();
            String content = getContent(entity);
            response = JSON.parseObject(content);
        }

        @Override
        public void failed(Exception e) {
            logger.warn("響應失敗", e);
        }

        @Override
        public void cancelled() {
            logger.warn("取消執行");
        }

    }

  • httpAsyncClientHttpClient性能對比,以及這三個方法的性能比較。後續我會進行對比測試。原因是本地服務響應太快,無法體現差異。

「Have Fun ~ Tester !」


「點擊閱讀閱文,查看FunTester歷史原創集合」


本文分享自微信公衆號 - FunTester(NuclearTester)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章