目錄
- 木桶理論應用在系統優化中
- 壓力測試如何實施
- 常用壓力測試工具選型
- 如何監控系統資源,定位性能瓶頸
- 針對測試報告進行針對性優化
- 使用JMeter進行壓力測試實踐
木桶理論又稱短闆理論,其核心思想是一隻木桶盛水多少,并不取決于最高的木闆,而取決于最短的那塊木闆。
木桶原理應用在系統分析中,即系統的最終性能取決于系統中性能表現最差的元件,為了提升系統整體性能,對系統中表現最差的元件進行優化可以得到最好的效果。

在網站系統中,使用者的通路請求到達伺服器,然後伺服器傳回資料并展示給使用者,這個過程要經過很多處理,每一個過程的低效都會影響系統整體表現出來的性能。
按照木桶理論,如果一台伺服器性能非常強大,擁有充足的記憶體資源和CPU資源,但是磁盤I/O性能不足,那麼系統的總體性能是取決于目前最慢的磁盤I/O速度,而不是目前最優越的CPU或者記憶體,此時,磁盤I/O就是系統的性能瓶頸。
典型的比如使用Redis進行存儲的系統,由于Redis本身性能非常優秀,通常情況下存儲并不會制約系統的性能,在海量請求的情況下,Redis的吞吐量會非常大,這時候制約系統的性能瓶頸就變成網絡帶寬。
性能測試在大型網站系統的設計和開發中非常重要,通常會和容量預估等工作結合在一起,穿插在系統開發的不同方案。
性能測試可以幫助我們及時發現系統的性能短闆,評估系統的能力,在這個基礎在上再進行針對性的性能優化。
同時,壓力測試還可以幫助我們驗證系統的穩定性和可靠性。
一個完整的性能測試方案通常包括以下幾個方面:
1.壓力測試及生成性能報告
壓力測試一個重點是如何産生壓力,通常可以通過自己編寫腳本模拟請求,或者使用成熟的壓測工具進行。
壓力測試很重要的一點是如何使得模拟壓測的資料盡量真實,越接近真實使用者越好。
2.根據性能報告定位系統瓶頸,進行針對性優化,測試和優化的工作可以和日常開發并行
壓力測試完成以後,我們會拿到一個壓測報告,這個報告通常會告訴我們系統的QPS、TPS、響應時延等資料,
這些資料可以讓我們對伺服器的性能有個整體的了解,發現存在的問題,但是不能幫助我們定位問題。
這個時候我們可以從系統的各個元件入手,關注系統的CPU、記憶體、IO、網絡,對比這些環節對整體性能的影響,确定性能問題是系統哪一部分造成的,然後針對性的在系統中逐個優化。
3.估算容量承載能力,合理規劃系統資源
進行壓力測試的一個重要目的是讓現有的伺服器資源發揮最大的價值,
經過前期的測試和分析,這時候我們對系統整體的性能有了一個認識,對伺服器的承載能力有了預估,
這個時候我們就可以結合業務規模配置伺服器數量,CDN資源等,讓最少的資源産生最大的價值。
壓力測試很關鍵的一點是如何産生壓力,選擇哪款測試工具很重要,大的網際網路公司如百度/騰訊等,都有專門的測試開發團隊,開發公司内部應用的測試工具,以便更好的适應公司的業務,作為SAAS服務的重要部分,幾個雲服務提供商也紛紛開放了壓測及性能監控服務。
大多數公司還是會選擇自己完成測試工作,這裡關注一下常用的壓力測試工具。
1.幾款流行的壓力測試工具
(1)JMeter
Apache JMeter是Apache組織開發的基于Java的壓力測試工具,用于對軟體做壓力測試,它最初被設計用于Web應用測試但後來擴充到其他測試領域。 它可以用于測試靜态和動态資源例如靜态檔案、Java小服務程式、CGI腳本、Java 對象、資料庫, FTP伺服器, 等等。
JMeter 可以用于對伺服器、網絡或對象模拟巨大的負載,來在不同壓力類别下測試它們的強度和分析整體性能。
另外,JMeter能夠對應用程式做功能回歸測試,通過建立帶有斷言的腳本來驗證你的程式是否傳回了期望的結果。
為了最大限度的靈活性,JMeter允許使用正規表達式建立斷言。
(2)LoadRunner
LoadRunner是惠普旗下一款自動負載測試工具,它能預測系統行為,優化性能。LoadRunner強調的是整個企業的系統,它通過模拟實際使用者的操作行為和實行實時性能監測,來幫助更快的确認和查找問題。此外,LoadRunner 能支援最寬範的協定和技術,量身定做地提供解決方案。
(3)其他測試工具
- Siege是一款開源的壓力測試工具,可以根據配置對一個WEB站點進行多使用者的并發通路,
記錄每個使用者所有請求過程的相應時間,并在一定數量的并發通路下重複進行。
- TCPCopy是一種請求複制(所有基于tcp的packets)工具,可以把線上請求導入到測試系統中去。
TCPCopy的特點是可以拷貝線上真實流量,模拟使用者資料。
2.性能測試工具的橫向對比
這裡對比主流的 JMeter和LoadRunner,一般來說,除了自研測試工具的公司,網際網路公司使用JMeter作為測試工具的較多。
JMeter | LoadRunner | |
開發語言 | 純Java開發 | 使用C語言開發 |
支援應用 | 對Java為主的系統支援較好 | 支援比較全面 |
是否收費 | 開源免費 | 商業軟體 |
學習成本 | 應用簡單,上手快,Java自定義測試計劃 | 功能複雜,學習成本高 |
協定支援 | 支援常見的HTTP/FTP/SMP等 | 支援較全面 |
自定義測試 | 支援使用Java編寫Sample | 使用完善的元件進行定制化測試 |
元件功能 | Thread Group, Samplers, Listeners, Pre & Post processors | 一套完整的測試元件,比如VU Generator, Controller, Analyzer, Load generator, Load calculator 和protocol advisor. |
壓力測試可以暴露系統性能問題,如高并發下通路緩慢,服務當機等,但是通過壓測不能具體到哪裡存在瓶頸,必須要在壓測同時配合适當的資源監控,幫助我們定位問題。
1.配置合理的資源監控方案
(1)使用nmon監控系統性能
nmon是Linux上廣泛使用的監控與分析工具,相對于其它一些系統資源監控工具來說,nmon所記錄的資訊是比較全面的,它能在系統運作過程中實時地捕捉系統資源的使用情況,并且能輸出結果到檔案中,然後通過nmon_analyzer工具産生資料檔案與圖形化結果。
nmon所記錄的資料包含以下一些方面:
● cpu占用率
● 記憶體使用情況
● 磁盤I/O速度、傳輸和讀寫比率
● 檔案系統的使用率
● 網絡I/O速度、傳輸和讀寫比率、錯誤統計率與傳輸包的大小
● 消耗資源最多的程序
● 計算機詳細資訊和資源
● 頁面空間和頁面I/O速度
● 使用者自定義的磁盤組
● 網絡檔案系統
(2)使用rpc.rstatd監控系統性能
rpc.rstatd通常配合LoadRunner一起使用,注意與系統服務rpc.statd進行區分。
rstatd背景程式可以從系統核心中擷取系統性能統計的相關資訊,将結果傳回給調用程式。
進行壓力測試時,LoadRunner用戶端通過給伺服器上的 rstatd 背景程式發送請求,來收集應用或資料庫伺服器的性能資料。
(3)針對不同的服務合理配置資源監控方案
以Java服務為例,在壓測同時可以對JVM虛拟機進行性能監控,這方面常用的有Jvisualvm、jps、jstack等。
下面是Jvisualvm的應用界面,可以監控本地和遠端的JVM執行個體運作狀态。
在壓力測試發現問題以後,就要進行有針對性的優化。對于不同的系統,這個過程的政策并不是确定的,但是大概可以劃分為以下幾個步驟:
1.定位性能瓶頸,找出系統存在的問題
不同系統的特點不同,在性能瓶頸上也有不同的表現,一般來說,下面的幾個方面通常存在比較大的優化空間:
(1)磁盤I/O及檔案操作
由于磁盤I/O讀寫的速度要比記憶體慢很多,程式在運作過程中,如果需要等待磁盤I/O完成,那麼低效的I/O操作會拖累整個系統。
(2)網絡操作
對網絡資料進行讀寫的情況與磁盤I/O類似。由于網絡環境的不确定性,尤其是對網際網路上資料的讀寫,網絡操作的速度可能比本地磁盤I/O更慢。
(3)CPU
對計算資源要求較高的應用,由于其長時間、不間斷地大量占用CPU資源,那麼對CPU的争奪将導緻性能問題。如科學計算、3D渲染等對CPU需求旺盛的應用。
(4)高并發下的上下文切換及鎖競争等
高并發程式如果沒有做好優化,存在大量的鎖競争,激烈得鎖競争将會明顯增加線程上下文切換的開銷,對性能造成極大的影響
(5)資料庫
大部分應用程式都離不開資料庫,而海量資料的讀寫操作可能是相當費時的。而應用程式可能需要等待資料庫操作完成或者傳回請求的結果集,那麼緩慢的同步操作将成為系統瓶頸。
2.确定調整目标,提出解決方案
找到系統的性能問題以後,需要作出對應的解決方案。
典型的影響性能的問題,比如:
(1)系統對高并發的場景響應不足,如資料庫連接配接池過低,伺服器連接配接數超過上限,資料庫鎖控制考慮不足等
(2)記憶體洩露,如在長時間運作下,記憶體沒有正常釋放,發生當機等
(3)資料庫優化不足,業務日益增長,關聯表衆多,SQL不夠優化等
定位到上述問題,接下來就是提出合理的調整目标,
比如伺服器資源有限,可以通過配置更多的機器,服務上雲等進行優化;
如果對高并發支援不好,就可以在代碼層面優化,提高并發支援;
資料庫性能問題,如慢查詢等問題,就可以進行 SQL語句優化等。
3.實施解決方案,進行疊代開發
上一步的分析給出了一個初步的性能優化方案,接下來就是針對方案中提到的内容進行針對性的改進。
這個過程可以應用靈活的思想進行疊代,在開發完成後,為了對比優化結果,可以對調優後的系統進行小範圍測試。
4.進行基準測試并分析調優結果
資料說明一切,性能優化的結果不能簡單的通過 “感覺系統變快了”來衡量,最好是通過對比優化前後的測試結果,用圖表的方式直覺的把優化結果展示出來。基準測試是指通過設計科學的測試工具和方式方法,實作對一類測試對象的某項性能名額進行定量的和可對比的測試。對比測試結果,結合容量評估等工作,可以讓系統發揮最大的效用。
一個階段的優化工作完成以後,最好是總結反思一下,比如本次優化是否達到了目标?系統的整體性能是否得到了改善?使用者體驗是否得到了提升?以及如何在接下來的開發工作中做的更好。
JMeter是目前流行的測試工具,這裡簡單的介紹一下相關的應用。
1.JMeter安裝與使用
Linux下可直接下載下傳安裝,MAC系統進入http://jmeter.apache.org/download_jmeter.cgi,下載下傳apache-jmeter-3.1.tgz。
下載下傳完畢後解壓,得到安裝包,進入到進入解壓目錄/bin/,單擊jmeter圖案,即可啟動JMeter。
2.基本元件簡介
應用JMeter需要熟悉一些基本的概念,這是編輯測試計劃的界面:
(1)Threads 線程組
這個元件主要用來控制Jmeter并發時産生線程的數量,在它的下一級菜單下隻有一個元件(線程組),可以這麼了解每個線程就是一個虛拟的使用者。所有的其他類型元件必須是(線程組)節點的子節點。
(2)ConfigElement 配置單元
和Sample元件一起工作,主要用來配置Sample如何來發起請求通路伺服器,這個東西的主要特點是可以把一些Sample的共同配置放在一個元素裡面友善管理,配置單元是有作用域的。作用域和樹的那個關系一樣越是上級節點的作用域越大,越是接近葉子節點的
作用域就越小,可以複寫上級作用域的配置。
(3)Timer 定時器
這個主要是用來調節(線程組),控制線程每次運作測試邏輯(比如說:送出請求)的時間間隔。當然這個下面還有很多類型的定時器,他們主要功能就是調節時間間隔,但個個元件之間的政策有很大不同。
(4)Pre Processors 前置處理器 / Post Processors 後置處理器
類似一個HOOK,在測試執行之前和執行之後執行一些腳本的邏輯。該元件我還沒有具體使用過,但大緻功能就是這樣,非重點元件。
(5)Assert 斷言
是指對于Sample完成了請求發送之後,判斷一下傳回的結果是否滿足期望。
(6)Listener 監聽器
這個元件不同于平時在Web程式設計的那種監聽器,他是伴随着Jemeter測試的運作而從中抓取運作期間的資料的一個元件,經常使用的是聚合報告元件,從裡面可以統計到測試的TPS,響應時間等關鍵測試資料。
3.進行第一個測試
(1)設定線程組參數
首先在TestPlan下面添加一個ThreadGroup元件,設定線程組元件各項參數。
線程數:最大測試時使用的線程數。
Ramp-Up Period : Jmeter達到指定最大線程數的時間。
循環次數 : 如果是Forever,線程組中的線程将不間斷的連續測試系統,當然也可以設定每個線程測試的次數,當完成了規定次數後,該線程将自動退出線程組。
(2)添加Sampler資訊
儲存線程組後,接着線上程組下面添加Sample元件,我們添加一個HTTP Request元件,
設定屬性如下圖:
Sampler表示用戶端發送某種格式或者規範的請求到服務端,是以有各種各樣的Sampler,如FTP/JDBC等。
這裡我添加了一個針對百度百科首頁的通路請求,端口為80,使用http協定。
(3)添加聚合報告的監聽器元件
添加一個Aggregate Report的listener的監聽器元件。
Aggregate Report 是 JMeter 常用的一個 Listener,中文被翻譯為“聚合報告”。
(4)啟動運作
點選RUN運作測試即可。然後可以看到本次測試的Aggregate Report。
4.Jmeter中的幾個重要測試名額釋義
可以看到,上面的聚合報告中有很多元度的資訊,簡單介紹幾個比較重要的名額。
Label | 每個 JMeter 的 element(例如 HTTP Request)都有一個 Name 屬性,這裡顯示的就是 Name 屬性的值 |
#Samples | 表示你這次測試中一共發出了多少個請求,如果模拟10個使用者,每個使用者疊代10次,那麼這裡顯示100 |
Average | 平均響應時間——預設情況下是單個 Request 的平均響應時間,當使用了 Transaction Controller 時,也可以以Transaction 為機關顯示平均響應時間 |
Median | 中位數,也就是 50% 使用者的響應時間 |
90% Line | 90% 使用者的響應時間,其他的幾個可以類推 |
Min | 最小響應時間 |
Max | 最大響應時間 |
Error% | 本次測試中出現錯誤的請求的數量/請求的總數 |
Throughput | 吞吐量——預設情況下表示每秒完成的請求數(Request per Second) |
Received / Sent KB/Sec | 每秒從伺服器端接收到/發送的資料量 |
作者:邴越
掃碼關注公衆号:架構進化論,獲得第一手的技術資訊和原創文章
如果文章對您有幫助,可以點選文章右下角【推薦】一下,您的鼓勵是作者堅持原創和持續寫作的最大動力!