性能測試入門指南:構建健壯應用程序的基礎知識
性能測試101:構建健壯應用的初學者指南
歡迎!本指南適用于任何構建了應用程序并希望確保在真實用戶開始使用時不會崩潰的人。我們將介紹性能測試的基礎知識,避免復雜的術語,專注于您可以采取的實際步驟,使您的應用程序健壯可靠。
您可能會覺得這篇文章太抽象,但請放心,下次我們將通過Java、Gatling和Docker Compose的實際示例來講解性能測試。
為什么性能測試很重要?
想象一下,您構建了一個應用程序,在數千用戶同時訪問之前工作正常,但您不知道如何處理這種負載。您正在擴展應用程序以滿足新用戶,但同時,您看到基礎設施成本不斷增長。在某個時刻,您可能決定停止增長,允許用戶體驗緩慢、降級的服務。
這就是性能測試發揮作用的地方,它通過事先測量性能并在實際使用前發現瓶頸來幫助您避免這種情況。
本文基于我自己的經驗,探討如何簡化生活,同時避免不必要的負擔。
在下文中,當我說"實例"時,指的是應用程序的單個運行副本。
第一步:定義目標
最重要的步驟是定義性能測試的目標:您到底想要得到什么結果?雖然您最終可以追求多個目標,但最好從只關注一個開始。
目標示例:
- 找到彈性極限,確定實例在崩潰前可以處理的每秒請求數(RPS),并定義保護它的彈性參數(如斷路器或隔板)
- 發現在處理RPS時發生的內存泄漏
- 建立基線,定義在生產中需要監控的重要響應時間的第95(或第99)百分位數
- 驗證擴展是否及時發生并調整擴展策略
您的目標將決定您需要運行的測試類型。
第二步:選擇正確的測試類型
有幾種類型的性能測試,每種都設計用于回答不同的問題。
負載測試
這模擬了實例上的預期用戶負載。
目標: 識別性能瓶頸并確定系統的正常操作容量。
示例: 在黑色星期五銷售期間測試電子商務網站的并發用戶數。
壓力測試
這將系統推到其正常操作限制之外,以找到其崩潰點。
目標: 確定系統在極端條件下的穩定性及其恢復過程(例如,它是優雅地崩潰還是災難性地失敗?)。
示例: 在登錄服務器上模擬兩倍于最大預期用戶負載,以查看其何時停止響應。
耐力測試
也稱為浸泡測試,這評估系統在持續、顯著負載下長時間的性能。
目標: 發現隨時間發生的內存泄漏、性能下降或連接問題。
示例: 在服務器上運行24小時測試,持續重用戶負載,以監控內存使用情況和響應時間。
峰值測試
這檢查系統在用戶負載突然急劇增加時的表現。與負載逐漸增加不同,此測試模擬流量的突然激增。
目標: 確定系統是否可以處理突然的活動爆發,以及它可以多快恢復并返回到正常操作水平。
示例: 在重大新聞爆發后測試新聞網站的性能,導致大量即時訪問者涌入。
容量測試
這側重于數據庫。它涉及用大量數據填充數據庫,然后測試應用程序的性能。這也稱為洪水測試。
目標: 分析系統在處理大量數據時的響應時間和行為。它有助于識別慢查詢或數據庫連接問題等問題。
示例: 查詢已填充數百萬條記錄的客戶數據庫,以查看搜索操作需要多長時間。
可擴展性測試
這衡量應用程序"向上擴展"或"向外擴展"以處理增加的用戶負載的能力。向上擴展涉及向現有服務器添加更多資源(如CPU或RAM),而向外擴展意味著向系統添加更多服務器。
目標: 確定應用程序通過添加更多資源來有效處理用戶流量增長的能力。
示例: 逐漸增加Web應用程序上的用戶負載,同時添加更多Web服務器,以查看每個用戶的性能是否保持一致。
第三步:使用存根隔離應用程序
良好的性能測試會隔離您的應用程序。如果您的應用程序調用外部服務,該服務的緩慢可能會使您的應用程序看起來很糟糕。為了防止這種情況,我們使用存根——這些外部依賴項的模擬版本——以確保我們只測試自己的代碼。
Wiremock是一個很好的工具。它靈活,可以模擬許多協議,如HTTP、SSE、GRPC和GraphQL。您還可以記錄請求/響應以動態創建存根。
但如果那個外部API通常很慢怎么辦?我們需要模擬這種情況。這就是我們可以在日常工作中加入一點混沌工程的地方。
使用混沌工程模擬延遲
要解決這個問題,您可以根據環境使用幾種工具集:
Docker
tc和netem:您使用tc命令向容器的虛擬網絡接口添加netem規則。- Pumba:Pumba本身作為容器運行,并與Docker守護進程交互,使用底層的
tc和netem來操作其他容器的網絡。例如,向名為my-app的容器添加2秒延遲:pumba netem --duration 5m delay --time 2000 my-app。
K8s
- Chaos Mesh:一個強大的平臺,用于注入故障,包括使用簡單YAML文件的網絡延遲
- LitmusChaos:另一個流行框架,具有預定義實驗的"ChaosHub",非常適合CI/CD集成
- Istio/Linkerd(服務網格):如果您已經在使用服務網格,它們具有內置功能來注入網絡延遲和其他故障
第四步:設置工具
您需要工具來生成負載并監控結果。
要實際生成負載并運行性能測試,您需要一個評估工具。流行的選擇包括:
- Gatling和K6是基于代碼的,非常適合希望將測試集成到CI/CD管道中的開發人員
- Apache JMeter具有用戶界面且功能強大,是那些喜歡較少代碼的人的不錯選擇
- Apache Benchmark(ab)非常適合從命令行進行快速簡單的測試
監控工具
在測試運行時,您需要了解底層發生了什么。這就是監控工具的用武之地。在現代世界中,我們有許多工具來提供它:
- OpenTelemetry:統一日志、指標和跟蹤的標準。這個話題太廣泛,無法在這里描述,但您可以在其官方文檔中了解更多
- Jaeger:一個流行的跟蹤監控工具
- Prometheus:用于收集指標的時間序列數據庫
- Grafana:這是一個可視化工具,用于從Prometheus中的數據創建儀表板。您可以在官方GitHub存儲庫中找到許多可重用的儀表板
第五步:了解指標和模式
關鍵指標監控
當然,這些取決于您的具體情況和目標。幾乎不可能一次完善所有指標。
- 系統指標: 這些都與操作系統資源相關——RAM內存、存儲、CPU、網絡帶寬、磁盤I/O等
- 應用程序指標: 這些都與您的應用程序相關。更準確地說,在Java世界中,您可以監控JVM內存區域、GC暫停和HTTP服務器指標,如成功請求數或連接池狀態
- 業務指標: 這類指標與業務活動相關,例如特定端點的延遲
關鍵彈性模式
彈性模式很重要,因為它們是旨在防止系統故障、保護資源并確保應用程序保持功能和響應的主動策略,即使其部分運行緩慢、失敗或處于極端負載下。
每個模式都解決特定類型的潛在故障,使整體應用程序更加健壯:
-
斷路器: 類似于電氣斷路器。它監控對外部服務的調用,如果故障達到閾值,電路"打開",后續調用立即失敗而不被嘗試。超時后,它移動到"半開"狀態,以查看服務是否已恢復,然后完全"關閉"。
它防止什么: 防止應用程序在已關閉或掙扎的服務上浪費資源,這阻止本地故障導致整個系統的級聯故障。
-
隔板: 以船體中的隔板命名,此模式將應用程序的部分隔離到獨立的資源池(如線程池)中。如果一部分失敗,它被限制在自己的隔板內,不會耗盡其他部分所需的資源。
它防止什么: 防止系統某部分的故障導致整個應用程序崩潰,并有助于避免內存不足錯誤。它確保故障隔離,因此即使一個功能關閉,其他功能仍可用。
-
超時: 一個簡單但關鍵的模式,您為等待外部調用的響應設置最大時間限制。如果服務在該時間范圍內沒有響應,調用會自動放棄。
它防止什么: 防止系統資源(如線程)無限期地等待慢服務而被阻塞,這避免了資源耗盡并保持應用程序響應。
-
重試: 自動重新嘗試已失敗的操作。它對瞬時錯誤最有效,如短暫網絡故障。通常配置重試之間的延遲(例如,"指數退避")以給服務時間恢復。
它防止什么: 防止臨時、間歇性故障被視為永久錯誤,提高操作的彈性和成功率。
-
速率限制器: 控制服務在給定時間段內接受的傳入流量或請求量。如果超過限制,限制器通常使用HTTP 429"請求過多"狀態拒絕請求。
它防止什么: 保護您的服務不被太多同時請求淹沒,防止系統過載,并幫助緩解拒絕服務(DoS)攻擊。
-
緩存: 涉及將頻繁訪問的數據副本存儲在比源(如內存中)訪問更快的位置。
它防止什么: 防止后端系統(如數據庫)上的不必要負載,并減少用戶的響應時間。這提高了性能,甚至可以在后端暫時關閉時保持應用程序的部分功能
第六步:記錄和分析結果
根據目標,收集不同類型的結果。期望每個測試運行應該在"新鮮"實例上執行,不受先前運行的影響。
以下是負載測試期間可以填寫的表示例:
| 運行 | 基線RPS | 乘數 | 持續時間 | 預期/實際請求數 | 中位數t | 平均t(ms) | p95 t(ms) | 錯誤率 | 其他指標 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 100 | 3 | |||||||
| 2 | 150 | 3 | |||||||
| 3 | 200 | 3 | |||||||
| 4 | 225 | 3 | |||||||
| 5 | 250 | 3 |
列說明
- 基線RPS – 您正在測試的"正常"每秒請求數
- 乘數 – 基線RPS在測試期間乘以此值。例如,您希望在特定時間段內將負載從100增加到100*乘數,從100到300
- 中位數t – 響應時間的第50百分位數,以毫秒為單位
- 平均t – 響應時間的平均值
- 錯誤率 – 處理期間失敗的請求數量
- p95 t(ms) – 響應時間的第95百分位數,以毫秒為單位。這意味著95%的請求比這個值快,這是用戶體驗的關鍵指標
- 其他指標 – 用于做出明智決策的特定指標
結論
性能測試可能看起來令人生畏,但通過從明確的目標開始并采取結構化方法,您可以系統地提高應用程序的可靠性。這不是關于通過或失敗;而是了解您的系統在壓力下的行為并使其更好。從小處開始,迭代,您將構建一個能夠承受現實世界需求的應用程序。
更多精彩內容 請關注我的個人公眾號 公眾號(辦公AI智能小助手)
對網絡安全、黑客技術感興趣的朋友可以關注我的安全公眾號(網絡安全技術點滴分享)
公眾號二維碼

公眾號二維碼


浙公網安備 33010602011771號