關於一個簡單介面的併發測試與優化記錄

劉之西東 發表於 2020-06-30

目的

通過測試瞭解高併發的各處細節,尋找制約因素;為軟硬架構設計提供優化參考。

前述

  • 優化前,該介面在測試環境的qps為140左右
  • 該介面的內部邏輯
    • 處理前1:開始計時
    • 處理前2:較驗IP白名單
    • 處理:
      • 查詢資料庫並快取
    • 處理後1:結束計劃,並提交日誌(用於形成效能報告)
      • 日誌通過REST API,最終寫入資料庫
  • 該介面特徵:
    • 內部處理簡單
    • 可優化點比較清楚

開始測試

  • 使用一個nio或aio的通道框架測試helloworld

    • 使用本機測試,qps約為:450萬(我的電腦 macbook pro 4c 16g)
      • 如果server端的服務執行緒,加個System.out.println;qps估計要降一半(親自跑過)
  • 使用solon.boot.jlhttp,測試helloworld(單機,單例項)

    • 使用本機測試,qps 約為:5萬(我的電腦 macbook pro 4c 16g)
    • 使用域局網測試(192.168.8.118),qps給為:2萬(2c 4g 虛擬機器)
  • 測試getAppByID(服務端為單機單例項;測試端為另一臺機,走的是內網)

    • 服務端測試機情況
      • 上面有8個java服務;docker服務(memcached,redis,mysql);
    • 初始測試
      • qps約為:140
    • 去掉三個觸發器
      • -不用快取,qps約為:600
      • +memcached,qps約為:1萬(memcached 在本機,應該有優勢;否則可能差些)
      • +二級快取(一級為本地快取),qps約為:1.4萬
      • 從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萬
    • +記效能 +記日誌 +白名單較驗,qps約為:320

優化三

  • 效能記錄,改為本地收集 + 5秒間隔提交
    • +記效能 +白名單較驗,qps約為:6000(應該還有優化空間)
    • +記效能 +記日誌 +白名單較驗,qps約為:800
  • 日誌級別動態可控,可在非必要時控制日誌提交量
    • 日誌約等於可沒有...進而減少這部分的IO(對於業務系統,這個控制是非常之必要)

後續方案嘗試

  • 優化四:
    • 將日誌記錄,調整為批量隔秒提交;進一步降低框架對應用的併發影響
  • 實驗一:
    • 對比測試:日誌管道模式提交,與代理抓取模式的差異

分析總結

  • 減少IO次數(主要是網路寫IO),可以大大提搞QPS。。。此為王道
  • 何為IO?一次IO輸出過程:
    • 應用空間 - > 核心空間 -> 裝置暫存器
    • 減少次數或避免IO可大大提高併發(像System.out.print...就是,都會影響高併發)
  • IO的總量有限...
    • 我們經常會看到,cpu、記憶體很底,但是併發壓不上去。。。就是大量的IO在排隊
    • 或者程式在一段時間失去了響應,過段時間又好了。。。也是大量的IO在排隊
    • 業務的程式,基本上是IO密集型的
    • 不管是多執行緒,還是非同步。。。但IO總量有限
      • 之前一直以為,非同步寫日誌對併發沒什麼影響;對單次請求效能無影響,但會佔用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"