無所不在的性能測試——《LoadRunner 沒有告訴你的》之五
提到性能測試,相信大家可以在網上找到很多種不同的定義、解釋以及分類方法。不過歸根結底,在大多數情況下,我們所要做的性能測試的目的是“觀察系統在一個給定的環境和場景中的性能表現是否與預期目標一致,評判系統是否存在性能缺陷,并根據測試結果識別性能瓶頸,改善系統性能”。
本文是《LoadRunner沒有告訴你的》系列的第五篇,在這篇文章中,我希望可以跟大家一起來探討“如何將性能測試應用到軟件開發過程的各個階段中,如何通過盡早的開展性能測試來規避因為性能缺陷導致的損失”。
因此,本文的結構也將依據軟件開發過程的不同階段來組織。
另外,建議您在閱讀本文前先閱讀本系列文章的第三篇《理發店模型》和第四篇《理解性能》。
需求階段
我們不可能將一輛設計載重為0.75噸的皮卡改裝成載重15噸的大型卡車,如果你面對的正是這樣的問題,那么恐怕你只能重做一輛,而且客戶不會為你之前那輛付錢。對于一個已經完成的應用系統來說也是如此。
如果我們在系統結構確定之前就能夠了解到系統的將要面對的壓力,用戶的使用習慣和使用頻度,我們就可以更早也更有效的提前解決或預防可能發生的性能缺陷,也將會極大的減少后期返工和反復調優所帶來的工作量。如果我們預期到系統的容量將會不斷的增長,我們還可以給出相應的解決方案來低成本的解決這類問題,就像上面那輛皮卡,也許你可以有辦法把20輛皮卡捆在一起,或者把15噸的東西分由20輛來運。
分析設計階段
系統性能的優化并不是要等待整個系統全部集成后才能開始的,早在分析設計階段,我們就可以開始考慮系統的技術架構和數據庫部分的優化。
數據庫通常位于整個系統的最底層,如果直到系統上線前才發現因為數據庫設計不合理而導致性能極差,通常使用任何一種方法來優化都已經于事無補了。要避免這類問題,最常見的做法是在數據庫結構確定后,通過工具或腳本向數據庫中注入大量的數據,并模擬各種業務的數據庫操作。根據對數據庫性能的觀察和分析,對數據庫表結構和索引進行調整以優化數據庫性能。
在系統的技術架構方面,要明白先進的技術并不是解決問題的唯一方法,過于強調技術的作用反而會將你帶入歧途。例如:某些業務雖然經常面臨著巨大的壓力,并且業務本身的復雜性決定了通過算法的優化來提高系統的性能收效甚微。但是我們知道用戶對于該業務的實時性要求并不高,并且返回結果對于不同用戶來說是相同的。那么我們完全可以考慮將每次請求都動態生成返回結果的方式改為每次用戶請求都返回一個定期更新的靜態頁面。
另外,所謂“先進技術”通常都會在帶來某一方面改進的同時帶來另一方面的問題,未經試驗就盲目的在系統中加入各種流行元素未必是最好的選擇。例如ORM可以提供一些方便,但是它生成的SQL是未經優化的,有時甚至比人工編寫的SQL效率更低。
最后,要知道不同廠家的設備性能是不同的,而且不同的硬件設備搭載不同的操作系統、數據庫、中間件以及應用服務器,表現出來的性能也是不同的。如果有足夠的資源,應當考慮提前進行軟硬件平臺的對比選型;如果沒有足夠的資源,可以考慮通過一些專業的組織或網站來獲取或購買相關的評估報告。
編碼階段
一片樹葉在哪里最難被發現?——當這片樹葉落在一堆樹葉里面的時候。
如果你只是在系統測試完成后才開始性能測試,那么即使發現系統存在性能缺陷,并且已經有了幾個可供懷疑的對象,但是當一段因為使用了不當的算法而導致執行效率很低的代碼藏身于一個龐大的系統中時,找出它是非常困難的。避免這種情況出現的方法是盡早開始核心業務代碼的性能測試,重點集中在對算法和實現方法的優化上。
另外,及早開始的測試也可以幫你更容易找到內存泄漏的問題。
測試階段
產品終于交到我們手上了,搭建測試環境,設計測試場景,執行測試,找到系統的最佳并發用戶數和最大并發用戶數,將系統進行分類,評判系統的性能表現是否滿足需求中定義的目標——如果有需求的話 ^_^
如果發現系統的性能表現與預期目標相去甚遠,則需要根據執行測試過程中收集到的數據來分析和識別性能瓶頸,優化系統性能。
在這個階段還有很多值得我們深入思考和討論的東西,在本系列后續的文章中,我們將會更多的關注這一部分的內容。
維護階段
維護階段通常遇到的問題是需要在實驗室中模擬客戶環境,重現在客戶那里發現的缺陷并修復缺陷。相比功能缺陷,性能缺陷與某一具體環境和場景的關聯更加密切,所以在測試前需要檢查生產環境中各服務器的資源利用率、系統訪問日志、應用服務器的日志、數據庫的日志。如果客戶使用了專門的系統來監測各個服務器的軟硬件資源使用情況的話,檢查該系統是否記錄下了軟硬件資源的異常或者警告。
與性能測試相關的其他測試
可靠性測試(Reliability Testing) 對于一個運營商級的系統來說,能夠保證提供7×24的連續穩定的服務是非常重要的。當然,你可以通過一些“高可用性(High Availability)”技術方案來增強系統的可靠性,但是對于系統本身的可靠性測試是不能被忽略的。
常用的測試方法是使用一定的負載長時間向服務器加壓,并觀察隨著加壓時間的延長,響應時間、吞吐量以及資源利用率的變化。要注意的是,所使用的負載應當是系統的最佳并并發用戶數,而不是最大并發用戶數。
可伸縮性測試(Scalability Testing) 對于一個系統來說,在一個給定的環境下,它的最佳并發用戶數和最大并發用戶數是客觀存在的,但是系統所面臨的壓力卻有可能隨上線時間的延長而增大。例如,一個在線購物站點,注冊用戶數量不斷增多,訪問站點查詢商品信息和購買商品的人也不斷的增多,我們應該用一種什么樣的方案,在不影響系統繼續為用戶提供服務的前提下來實現系統的擴容?
一種常用的方案是使用負載均衡(Load Balance)和集群(Cluster)技術。但是在我們為客戶提供這種方案之前,需要先自己進行測試,保證該技術的有效性——我們是否真的可以通過簡單的增加服務器數據和修改某些參數配置,就能夠使得系統的容量得到線性的增長?
可恢復性測試(Recoverability Testing) 雖然我們已經可以準確的估算出系統上線后將要面對的壓力,并且可以保證系統的最佳并發用戶數和最大并發用戶數是足以應對這些壓力的,但是這個世界上總是有些事情上我們所無法預料到的——例如9.11事件發生后,AOL的網站訪問量在短時間內增長到了平時的數十倍。
我們無法保證系統可以在任何情況下都能為用戶正確無誤的提供服務,但是我們需要確保當意外過去后,系統可以恢復到正常的狀態,并繼續后來的用戶提供服務——就像從未發生過任何事情一樣。
如果要實現“可恢復性測試”,我們可以借助于測試工具或腳本來逐漸的增大并發用戶數,直至并發用戶數已經超過了系統所能承受的最大并發用戶數,并導致軟硬件資源利用率飽和,響應時間無限延長,大量的請求因為超過響應時間要求或無法獲得響應而失敗;之后,我們逐漸的減少并發用戶數,并觀察資源利用率、響應時間、吞吐量以及交易成功率的變化是否與預期目標一致。
當然,這一切的前提是在系統負載達到峰值前,Server一直在頑強的掙扎著而沒有down掉 ^_^

性能測試,并非網絡應用專屬
軟件的性能和性能測試都是伴隨著網絡應用的興起而逐漸被重視起來的,但是軟件性能和性能測試卻并非網絡應用的專屬名詞,因為單機版的應用同樣需要考慮性能問題。下面舉幾個簡單的例子來方便大家的理解:
1. 當使用Word來編輯一個500多頁,并包含了豐富圖表、圖片和各種格式、樣式信息的文檔時,是否每次對大段的文字或表格的修改、刪除或重新排版,都要等待系統花幾秒鐘的時間進行處理?
2. 當在Excel中使用嵌套的統計和數學函數對幾萬行記錄進行統計分析時,是否每次都要兩三分鐘才能看到結果?
3. 殺毒軟件是否每次都要花費兩個小時才能完成一次對所有的分區的掃描?
4. 是否每次在手機的通訊簿中根據姓名搜索某個人的聯系方式都要三四秒鐘才有響應?
如果大家有興趣,也可以通過Google搜索到更多的有關單機應用性能測試的資料。
點擊這里了解整個系列的創作進度,查看文章目錄,或瀏覽已經完成的文章。