一次壓測實戰的覆盤

有夢想的老王發表於2020-07-24

前言

​ 由於筆者在電商公司,算二三線的大廠了吧,最近跟京東拼的火熱。因為818大促在即,本人所負責的專案,在大促期間壓力會比較大,有必要對系統主要介面做一次壓測。下面覆盤了,我這次壓測從發現問題分析問題總結的全過程,希望能對你有所啟發。

問題

​ 壓測時發現系統的瓶頸在於cpu,那麼考慮為啥瓶頸在cpu,以及如何優化?

發現過程

​ 測試環境使用jmeter進行介面壓測,然後逐步調大併發度,觀察系統吞吐量,然後在ares平臺(類似skywalking)上監測JVM記憶體,CPU,執行緒狀態等

​ 然後發現,gc資訊和記憶體資訊很穩定,但是cpu會達到90%,這時檢視jvm的執行緒狀態,發現又70%左右的執行緒處於waiting或者timed_waiting狀態;

​ 初步推算會不會是執行緒過多導致cpu過高。

問題分析

首先分析介面的執行流程以及執行緒池的使用場景

​ 簡單的描述一下:客戶端發來一個請求,由容器執行緒接收,然後通過common執行緒池建立多個執行緒去併發執行,然後通過latch進行等待,等所有的common執行緒執行完在合併然後返回給客戶端;每一個common執行緒是一個小任務可以稱為“單品查傭”,common執行緒會首先使用select執行緒池建立4個並行任務進行引數轉換,並且通過latch進行等待然後合併,緊接著繼續併發進行查詢,此時也是使用select執行緒池先去併發查詢然後再common執行緒裡面合併計算結果。

上圖顏色相同的表示在同一個執行緒或者執行緒池,通過上圖可以大概得出common執行緒池和select執行緒池執行緒個數比為1:5(是不是真的這麼去設定執行緒池大小呢?)。

開始壓測

壓測環境和結果

說明:由於之前做過一次優化,基本將DB和ES的壓力因素去除了,JVM中的記憶體,頻寬因素基本也排除了,目的就是為了看CPU壓力。

環境:首先根據業務場景,分析由於整個流程中有多次的RPC呼叫或者Redis等資料請求所以初步將任務定義為IO等待型,目標機器配置2C4G * 2 ,同用的測試引數

工具:Jmeter

壓測結果:

結果分析

  1. 在common,select執行緒數分別為5,25時(第一組資料),隨著併發數的上升cpu並沒有徒增,穩定在80%左右,但是tps並沒有線性增長,平均響應時間也明顯下降了不少,但是發現併發數的提高沒有將CPU壓到極限,開始懷疑是業務執行緒相關了。

這個時候通過ares平臺分析JVM執行緒狀態,發現如下:

分割線----------------------------------------------------------------------------------------------------------------

然後檢視等待狀態的執行緒,發現大部分是select的執行緒,而且大部分處於getTask方法上面,熟悉執行緒池執行原理的同學都知道,這個是在獲取任務,因為沒有任務了所以阻塞等待了,所以可以指定select的執行緒個數明顯設定過多。從另一方面也說明,common和select的執行緒個數比不對,不是按照分析1:5 設定。因此下面的測試降低select的執行緒數。

  1. common和select執行緒數分別為5,10時,減少了select執行緒的個數,cpu和tps和剛剛差不多,但是select的等待執行緒少了,這裡慢慢發現common執行緒個數對tps和cpu有一定的影響,而select執行緒個數影響不大。這時發現增大併發數並不會顯著提高TPS,但是響應時間是會明顯增加。

  1. common和select執行緒數分別為10,10時,大部分common執行緒在latch上面等待,會不會是select執行緒不夠用?隨著併發數增多,響應時間在下降,但是tps並沒有增加,具體可以看下圖,common在latch上面(和程式碼對應),

  1. common和select執行緒數分別為10,20時,通過觀察執行緒狀態,select執行緒出現等待getTask,cpu會到達94%,tps相應的也會增加,併發數的增加也只是提高了tps,但是會導致響應時間的下降;另外併發增大時,select執行緒都在執行任務,common執行緒出現在latch上面等待,但是響應時間慢了,cpu忙了,因為所有的select執行緒都在執行,執行緒上下文切換(CS)次數肯定會大量增加(可以vmstat檢視),

初步總結

總結: 綜合這4組壓測資料,初步有個簡單的結論,common執行緒池決定了整體的吞吐量(TPS),但是吞吐量提升的的同時,CPU和響應時間也會增大,而select執行緒需要依賴common執行緒的個數,比例在1.5-2之間,少了會導致TPS上不去響應時間也會增加,大了CPU上去了,最終也會導致響應時間的增加,所以common和select執行緒數的選擇需要有據可詢。那麼針對當前的機器配置,兼顧TPS,響應時間和CPU使用率(低於90%),common線核心程池數設定8,select執行緒數設為12,此時100的併發數,CPU最高在90%,TPS在760,平均響應時間100ms。

優化方向:

通過執行緒狀態和業務流程的分析,我們發現可以將併發部分的業務流程進行細分,主要劃分為IO等待型任務和CPU計算型任務,然後使用不同的執行緒池,IO型的就多設定執行緒數,CPU型的就少一點。有個初始經驗值

IO 型:2 * CPU個數

CPU型:CPU個數 + 1

另外,分析過程中為了方便執行緒池配置的變更和觀察使用公共包ThreadPoolManager來管理系統所有的執行緒池。有需要的可以使用

壓測時機器的其他指標,供參考

Pidstat

Vmstat

Mpstat

相關文章