java接口壓測:當(dāng)接口不是瓶頸,機(jī)器cpu和網(wǎng)絡(luò)帶寬對(duì)接口qps的影響

最近有客戶對(duì)接口的qps要求特別高,所以我對(duì)接口做了很多壓力測試和代碼優(yōu)化。代碼優(yōu)化主要是在減少網(wǎng)絡(luò)請求,以及避免大量使用循環(huán),把有些邏輯拆到定時(shí)器,然后就是熱點(diǎn)數(shù)據(jù)緩存到redis以及jvm內(nèi)存中。
除了接口優(yōu)化,我想知道,當(dāng)接口不是瓶頸的時(shí)候,機(jī)器的性能和網(wǎng)絡(luò)帶寬對(duì)接口qps的影響。于是,我做了以下實(shí)驗(yàn)。

實(shí)驗(yàn)?zāi)康?/h4>
  • 了解cpu和接口qps的關(guān)系
  • 了解接口數(shù)據(jù)包大小和qps的關(guān)系
  • 了解網(wǎng)絡(luò)帶寬和接口qps的關(guān)系

部署api的實(shí)驗(yàn)三臺(tái)機(jī)器配置分別為(阿里云內(nèi)網(wǎng)測試)

  • 阿里云4核4g
  • 阿里云8核16g
  • 阿里云16核32g

測試工具

  • wrk

部署wrk的機(jī)器配置

  • 阿里云8核16g

wrk測試參數(shù)

wrk -t16 -c400 -d30s -s test-nginx.lua --latency  http://172.26.68.135:9000/test/testApi

test-nginx.lua

wrk.method = "POST"
wrk.headers["Content-Type"] = "application/json"
wrk.body   = "{ \"number\": 2}"

上面的參數(shù)是本地內(nèi)網(wǎng)環(huán)境下最優(yōu)參數(shù),測試過程中需要更改接口ip和端口。

測試代碼

   Cache<String, List<TestNginxResp>> cache = Caffeine.newBuilder()
            .expireAfterWrite(1000, TimeUnit.MINUTES)
            .maximumSize(1000)
            .build();

    @PostMapping("/testApi")
    public Response<List<TestNginxResp>> getTest(@Valid @RequestBody TestNginxReq req) {
        List<TestNginxResp> cacheList = getCache(req);
        if (cacheList != null) {
            return Response.ok(cacheList);
        }
        List<TestNginxResp> list = new ArrayList<>();
        for (int i = 0; i < req.getNumber(); i++) {
            list.add(TestNginxResp.buildDefault());
        }
        cachePush(req, list);
        return Response.ok(list);
    }

    private List<TestNginxResp> getCache(TestNginxReq req) {
        String key = "test-api".concat(String.valueOf(req.getNumber()));
        List<TestNginxResp> resps = cache.getIfPresent(key);
        return resps;
    }

    public void cachePush(TestNginxReq req, List<TestNginxResp> klineRespList) {
        String key = "test-api".concat(String.valueOf(req.getNumber()));
        cache.put(key, klineRespList);
    }

請求參數(shù)示例

{
    "number":2
}

返回接口實(shí)例

{
   "code" : 200 , 
    "msg" : "ok" , 
    "body" : [
        {
            "name" : "nginx" ,
            "author" : "Igor Sysoev" , 
            "version" : "1.18" , 
            "desp":"高性能代理工具"
        },
        {
            "name" : "nginx" ,
            "author" : "Igor Sysoev" , 
            "version" : "1.18" , 
            "desp":"高性能代理工具"
        }
    ]
}

接口說明

參數(shù)中number傳入數(shù)字幾,就返回幾個(gè)上面的bean。通過這個(gè)test-nginx.lua中的number控制返回?cái)?shù)據(jù)包的大小。接口第一次是通過循環(huán)創(chuàng)建list,然后放入Caffeine的本地緩存。下次同樣數(shù)量就直接從緩存拿。

影響qps的因素

  • 1.網(wǎng)絡(luò)
  • 2.cpu
  • 3.內(nèi)存
  • 4.磁盤
    首先分析,我們上面的接口調(diào)用過程中,主要是通過從Caffeine的本地緩存中去拿取數(shù)據(jù),沒有mysql,redis,或者其他第三方調(diào)用,所以接口不可能成為瓶頸。我們的變量是number,也就是可以改變返回?cái)?shù)據(jù)包的大小。這里不存在磁盤的讀寫性能問題,全部走jvm內(nèi)存,jvm 2g堆內(nèi)存足夠了,所以機(jī)器內(nèi)存大小對(duì)本次實(shí)驗(yàn)沒影響。
綜上,磁盤性能和內(nèi)存的因素在本次測試中沒什么影響。本次主要是測試`cpu`和`網(wǎng)絡(luò)`對(duì)qps的影響。

實(shí)驗(yàn)結(jié)果

編號(hào) 機(jī)器 number 數(shù)據(jù)包 qps 傳輸速度 cpu使用程度
1 4核 10 2.03kb 23191.98/s 30.01MB/s 4核全打滿
2 4核 391 77.57kb 4301.49/s 187.03MB/s 4核全打滿
3 4核 600 119.00kb 2812.82/s 187.59MB/s 4核全打滿
4 8核 10 2.03kb 42986.40/s 55.63MB/s 8核全打滿
5 8核 391 77.57kb 6870.61/s 300.52MB 8核未打滿
6 8核 600 119.00kb 4497.81/s 300.62MB 8核未打滿
7 16核 10 2.03kb 76086.64 98.47MB/s 16核全打滿
8 16核 391 77.57kb 6901.07/s 300.44MBs 16核未打滿
9 16核 600 119.00kb 4517.75 300.90MB 16核未打滿

備注:上面數(shù)據(jù)包大小是指:一次返回?cái)?shù)據(jù)包大小(只包括接口數(shù)據(jù),不包括tcp請求頭之類)。傳輸速度的峰值主要和網(wǎng)絡(luò)帶寬相關(guān)。

實(shí)驗(yàn)結(jié)果分析

  • 對(duì)比5,6或者8,9號(hào)實(shí)驗(yàn)
    現(xiàn)象為發(fā)現(xiàn)都是cup未打滿,但是傳輸速度300M/s左右。

    • 結(jié)論1:推斷這里cpu不是瓶頸,網(wǎng)絡(luò)帶寬是瓶頸。極限值300M/s,提工單問了阿里云,我們的機(jī)器內(nèi)網(wǎng)帶寬為2.5Gbps,的確帶寬極限下載速度為300M/s。
    • 結(jié)論2:在每次請求數(shù)據(jù)量變大后,帶寬打滿了,qps下降了,說明包越大,接口越慢。(這很容易理解,馬路就那么寬,車變多了,車速就慢了)
  • 對(duì)比1,4,7號(hào)實(shí)驗(yàn)。

    現(xiàn)象為數(shù)據(jù)量為10條,包很小,全部都是cpu打滿,然后傳輸速度依次遞增,最大為98.47MB/s,沒有達(dá)到極限值300M/s,qps隨cpu核心數(shù)遞增。

    • 結(jié)論1:這里帶寬不是瓶頸,cpu是瓶頸,且,cpu數(shù)量越多,qps越高,qps基本是和cpu核心數(shù)成正比。
    • 結(jié)論2:如果繼續(xù)購買32核cpu,傳輸速度沒有達(dá)到300M/s的情況下,qps會(huì)更高。
  • 對(duì)比5,8號(hào)或者6,9實(shí)驗(yàn)

    現(xiàn)象:5,8號(hào)都是391條,數(shù)據(jù)包很大。傳輸速度300M/s,cpu都沒打滿,cpu雖然加了,但是qps沒變。(6,9一樣)

    • 結(jié)論1:這里cpu不是瓶頸,帶寬是瓶頸,所以當(dāng)cpu增加的時(shí)候,qps并沒有對(duì)應(yīng)增加。
    • 結(jié)論2:當(dāng)帶寬打滿了,繼續(xù)增加cpu,qps基本不會(huì)有變化。

總結(jié)

  • 當(dāng)帶寬沒打滿,增加cpu能夠增加qps。
  • 當(dāng)帶寬打滿了,增加cpu不能夠增加qps
  • 當(dāng)帶寬都打滿了,cpu不變,每次包越大qps越低
  • 當(dāng)一直增加cpu,但是一直打不滿帶寬的時(shí)候,就能說明瓶頸在接口,需要查看是否是mysql,redis或者程序中的哪些邏輯成為瓶頸。

最后上一張wrk測試接口圖,以及工單和阿里云溝通的截圖

wrk測試結(jié)果.png

阿里云工單.png

小tip

  • 極限壓力測試需要一個(gè)相對(duì)干凈的機(jī)器,避免機(jī)器上面應(yīng)用對(duì)接口性能的影響。為了測試機(jī)器性能對(duì)接口影響,甚至需要需要各種不同參數(shù)的機(jī)器,比如4核8g,8核8g,16核8g。這個(gè)時(shí)候可以在阿里云上開一臺(tái)按量付費(fèi)的機(jī)器,上面很干凈,然后做完測試就關(guān)閉,甚至釋放掉,一個(gè)小時(shí)也就一兩塊錢,很便宜,幾乎不耗資源。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容