
容量測試到底測什么一次對話理清同時在線和并發請求和同事討論容量測試發現很多人把同時在線和并發請求攪在一起。這篇把這段對話記錄下來幫你看清容量的本質。文章目錄容量測試到底測什么一次對話理清同時在線和并發請求一、起點一個常見的判斷1.1 同事的初始判斷1.2 先搞清兩個概念二、如果只看同時在線容量確實可以非常大2.1 無狀態架構在線用戶幾乎不花錢2.2 那有session的系統呢三、但是在線人數越高并發請求越高3.1 統計關系3.2 容量和并發是一個連續光譜3.3 一個實際例子四、并發請求的真正瓶頸在哪4.1 一個請求進來的真實開銷4.2 瓶頸清單4.3 一個并發請求的開銷五、容量測試到底測什么5.1 測的是第一個被打破的瓶頸5.2 各層監控指標5.3 常見場景六、總結6.1 三個結論6.2 一句話一、起點一個常見的判斷1.1 同事的初始判斷同事做政務系統要搞容量測試。他的判斷是容量測試應該只和服務端內存有關系吧session或者jwt也占用不了多少內存容量應該可以非常大。乍一看沒毛病——一個JWT字符串幾百字節一個session對象也就存點用戶信息內存開銷確實不大。那同時在線幾萬人內存也吃不了多少。容量瓶頸不該是內存吧但這個判斷有一個隱藏的概念混淆。1.2 先搞清兩個概念同時在線容量并發請求含義多少用戶登錄著、在用系統服務器同一時刻在處理多少請求對服務器的直接壓力JWT幾乎為零session很小每個請求吃線程連接CPU瓶頸在哪幾乎沒有線程池/連接池/CPU/數據庫這是兩個完全不同的東西。很多開發者嘴上說著系統容量要支撐一萬用戶實際上擔心的是一萬用戶同時點按鈕服務器扛不扛得住——前者是容量問題后者是并發問題。二、如果只看同時在線容量確實可以非常大2.1 無狀態架構在線用戶幾乎不花錢現在的系統基本都用JWT。用戶登錄后拿到一個tokentoken存在客戶端瀏覽器localStorage或Cookie。服務器不存任何東西。用戶登錄 → 服務器簽發JWT → 返回給客戶端 ↓ 用戶后續請求 → 帶上JWT → 服務器驗簽 → 處理請求 ↓ 請求結束 → 服務器什么都不留用戶拿不到token時在瀏覽頁面、填表單、看數據——這段時間對服務器來說這個用戶不存在。服務器不給他分配線程、不分配連接、不分配內存。所以同時在線10萬人和100人對服務器來說沒區別——因為大部分在線用戶此刻沒有在發請求。2.2 那有session的系統呢有同事會說我們的系統用Tomcat的HttpSession每個用戶在服務端存一份session這不就占內存了嗎算一筆賬。一個session里實際存什么數據大小估算用戶信息id、姓名、賬號~200字節機構信息id、名稱~100字節角色列表幾個角色ID~50字節權限標識如果是角色ID而非逐個權限~100字節合計不到1KB1000人在線session內存不到1MB。10000人在線也就幾MB。跟服務器動輒幾個G的內存比完全可以忽略。所以無論session還是JWT在線人數本身都不是瓶頸。同事最初的判斷方向是對的——容量確實可以非常大。三、但是在線人數越高并發請求越高3.1 統計關系到這里同事說那容量不是問題啊隨便扛。但這里有個統計關系一個系統在相關條件不變化同時在線用戶數量越多并發會越高。100個人在線同一時刻可能有5個人在點按鈕。10000個人在線同一時刻可能有500個人在點。在線人數上去了并發請求自然跟著上去。并發請求數 ≈ 同時在線人數 × 用戶活躍率 用戶活躍率 用戶在單位時間內發起請求的概率不同系統的用戶活躍率差異極大系統類型用戶活躍率說明政務OA低大部分時間在看頁面、填表幾秒點一次電商日常中瀏覽、加購物車、搜索電商秒殺極高所有人同時點搶購按鈕即時通訊高收發消息、狀態同步幾乎一直在請求所以不能脫離用戶行為談容量。容量不是孤立的能掛多少在線用戶而是這些在線用戶產生的高并發服務器扛不扛得住。3.2 容量和并發是一個連續光譜容量測試 并發測試 能掛多少在線用戶 在線用戶產生的高并發扛不扛得住 ←————————————————————————————→ 統計橋梁用戶活躍率兩者不是對立的是同一條鏈路上的兩端。容量測試關注左端——系統能容納多少在線用戶。并發測試關注右端——這些用戶產生的請求高峰能不能扛。中間的橋梁就是用戶行為模式。3.3 一個實際例子某政務系統預期5000人同時在線。做容量測試時要算的不是5000個session占多少內存而是5000人在線 × 用戶活躍率假設10%在同時操作 500個并發請求 ↓ Tomcat默認maxThreads200 → 不夠要調大 數據庫連接池默認20 → 遠遠不夠要調大 ↓ 這才是容量測試要回答的問題瓶頸不在5000人在線瓶頸在5000人產生的500個并發請求。四、并發請求的真正瓶頸在哪4.1 一個請求進來的真實開銷既然瓶頸在并發請求那一個請求到底吃服務器什么資源HTTP請求到達 ↓ Tomcat線程池分配線程maxThreads默認200 ↓ 從連接池拿數據庫連接默認8~20個 ↓ 執行業務邏輯CPU計算、JWT驗簽、序列化 ↓ 查數據庫可能等待鎖、等待IO ↓ 返回響應 ↓ 釋放線程和連接每一環都可能先于內存成為瓶頸。4.2 瓶頸清單瓶頸默認上限說明線程池Tomcat默認200200個并發請求就開始排隊跟內存無關數據庫連接池Druid/HikariCP默認8~20拿不到連接的請求要么等要么超時CPU看核數JWT驗簽、序列化、加解密、業務計算數據庫本身幾百~上千并發鎖競爭、慢查詢數據庫比應用服務器先扛不住內存看配置session/JWT確實占不了多少4.3 一個并發請求的開銷不要把一個用戶在線和一個請求處理搞混資源一個在線用戶空閑一個正在處理的請求線程無一個線程棧空間512KB~1MB數據庫連接無一個連接連接對象會話狀態內存session/JWT ~1KB結果集、序列化緩沖、臨時對象CPU無JWT驗簽、業務計算、序列化1000個并發請求光線程棧就吃掉1GB內存。而且線程切換的CPU開銷比內存更致命。所以容量可以非常大這句話對了一半——在線用戶的容量確實很大但他們產生的并發請求打到的瓶頸不在內存在別的地方。五、容量測試到底測什么5.1 測的是第一個被打破的瓶頸容量測試不是應用服務器內存能掛多少session而是從用戶請求到數據庫返回這條鏈路上哪個環節最先斷。不斷加壓觀察哪個指標先異常逐漸增加在線用戶數或直接加并發請求 ↓ 監控每一層的指標 ↓ 第一個先撐不住的環節 系統的真實容量上限5.2 各層監控指標層次監控什么異常表現應用服務器CPU、內存、線程數、GCCPU持續80%、頻繁Full GCWeb容器活躍線程數、請求隊列長度線程滿、請求排隊超時連接池活躍連接數、等待連接數連接耗盡、請求等待數據庫活躍會話數、鎖等待、慢SQL鎖沖突、SQL變慢網絡帶寬、連接數、丟包響應時間飆升5.3 常見場景場景最先斷的環節解法方向政務OA數據庫連接池默認太小調大連接池上限查詢密集型數據庫慢SQL加索引、優化SQL、讀寫分離計算密集型應用服務器CPU加機器、異步化秒殺類數據庫行鎖隊列削峰、緩存六、總結6.1 三個結論同時在線和并發請求是兩個概念——在線用戶的內存開銷確實很小session或JWT都不到1KB可以忽略但在線人數越高并發越高——兩者通過用戶活躍率關聯不能脫離用戶行為談容量瓶頸永遠在并發請求層——線程池、連接池、CPU、數據庫這些才是容量上限的真正決定因素6.2 一句話容量測試不是測能掛多少用戶是測這些用戶一起點的時候哪個環節先斷。