目的
通過測試,了解高並發需求的各處細節,尋找制約因素;為軟件框架 和 硬件架構提供優化參考。
前述
- 優化前,目標接口在測試環境的qps為160左右
- 目標接口的內部邏輯
- 處理前1:開始計時
- 處理前2:較驗IP白名單[rpc]
- 處理:
- 查詢數據庫並緩存
- 處理后1:結束計時;提交性能報告[rpc];提交輸入輸出日志[rpc]
- 日志通過RPC,最終寫入數據庫
- 目標接口特征:
- 內部處理簡單
- 可監測點比較清晰
開始測試
-
使用一個nio或aio的通道框架測試helloworld
- 使用本機測試,qps約為:450萬(我的電腦4c 16g)
- 如果server端的服務線程,加個
System.out.println;qps約為:20萬(縮了20多倍)
- 如果server端的服務線程,加個
- 使用本機測試,qps約為:450萬(我的電腦4c 16g)
-
使用solon.boot.jlhttp,測試helloworld(單機,單實例)
- 使用本機測試,qps 約為:5萬(我的電腦4c 16g)
- 使用域局網測試(192.168.8.118),qps約為:2萬(2c 16g)
-
測試目標接口 getAppByID (服務端為單機單實例;測試端為另一台機,走的是內網)
- 服務端測試機情況
- 上面有8個java服務;docker服務(memcached,redis,mysql);
- 初始測試
- qps約為:160
- 去掉三個觸發器(即前后處理,相當於Spring的過濾器)
- -不用緩存,qps約為:600
- +memcached,qps約為:1萬(memcached 在本機,應該有優勢;否則可能差些)
- +二級緩存,qps約為:1.5萬
從DB角度思考,如果涉及寫。。。qps只能靠DB的硬件提升了(量大時,還要靠分庫分表)
- 加上觸發器 + 二級緩存
- +記性能,qps約為:750
- +記性能 +記日志,qps約為;240(異步http提交日志;可能存儲在本機會有較大負影響;
sev->http->db->磁盤) - +記性能 +記日志 +白名單較驗,qps約為:160
- +白名單較驗,qps約為:900
- 服務端測試機情況
優化一
- 將okhttp異步,改為線程池加同步(okhttp自帶的異步,因為有融斷機制性能差些)
- +記性能 +記日志,qps約為;320(異步http提交日志;明明是異步了,為什么還這么低?因為還有IO頻次)
- +記性能 +記日志 +白名單較驗,qps約為:200
優化二
- 為白名單增加10s本地緩存
- +白名單較驗,qps約為:1.1萬(::從900提到1.1萬了;不同時間測值會有波動)
- +記性能 +記日志 +白名單較驗,qps約為:320
優化三
-
性能記錄,改為本地收集 + 5秒間隔提交(可稱為緩沖模式)
- +記性能 +白名單較驗,qps約為:6000(應該還有優化空間)
- +記性能 +記日志 +白名單較驗,qps約為:800
-
日志級別動態可控,可在非必要時控制日志提交量(對於業務系統,這個控制是非常之必要)
//日志級別動態切換控制 WaterClient.Config.subscribe("sponge", (set)->{ int level = set.get("rock_log_level").getInt(); WaterLogger.setLevel(Level.of(level)); });
優化四
- 優化性能記錄的緩沖器,改為1秒間隔提交
- +記性能 +白名單較驗,qps約為:15000(::對業務處理幾乎無影響了)
- 日志改為本地隊列收集+批量打包提交(可稱為管道模式)
- +記性能 +記日志 +白名單較驗
* 空時1秒間隔,單包最多100個日志:qps約為:5000
* 空時1秒間隔,單包最多200個日志:qps約為:10000
- +記性能 +記日志 +白名單較驗
后續嘗試
- 實驗一:
- 對比測試:日志管道模式提交,與代理抓取模式的差異
分析總結
- 減少IO次數,可大大提高 QPS。。。此為王道
- 何為IO?一次IO輸出過程:
- 應用空間 -> 內核空間 -> 設備寄存器
- 減少次數或避免IO可大大提高並發(像System.out.print...就是,都會影響高並發)
- IO的總量有限...
- 我們經常會看到,cpu、內存很底,但是並發壓不上去。。。就是大量的IO在排隊
- 或者程序在一段時間失去了響應,過段時間又好了。。。也是大量的IO在排隊
- 業務的程序,基本上是IO密集型的
- 不管是多線程,還是異步。。。但IO總量有限
- 之前一直以為,異步寫日志對並發沒什么影響;對單次請求性能無影響,但會占用IO資源
- 我們經常會看到,cpu、內存很底,但是並發壓不上去。。。就是大量的IO在排隊
附:
- 工具安裝
# centos 版
yum install -y https://github.com/scutse/wrk-rpm/releases/download/4.1.0/wrk-4.1.0-1.el7.centos.x86_64.rpm
# mac 版
brew install wrk
- 測試代碼
wrk -t10 -c200 -d10s --latency "http://10.0.0.79:1013/getAppByID?appID=10970"
