導致系統性能失敗的十個原因
很多軟件系統由于性能問題導致了失敗,在開發生命周期和性能測試生命周期的每個階段都存在導致性能失敗的原因。有時候,性能問題是無法控制的,它不在項目經理、技術架構師或性能工程師的控制范圍之內。從業務和個人層面來看,大多數的系統性能失敗僅僅是因為性能工程師、開發人員、 DBA、業務團隊和利益相關者之間從一開始就缺乏溝通,這導致了許多其他問題,這些問題將直接影響應用程序的性能和 ROI。對任何應用/產品進行有效性能測試的唯一目標是實現令人滿意的投資回報。性能測試和軟件工程是有風險的,并且總是需要從開發的早期階段開始,進行大量的反復試驗。
系統性能的失敗必須與其他業務問題進行類似的處理。了解問題出在哪里,為什么會出問題,以及如何預防。在大多數場景中,需要每個人都了解/理解端到端全生命周期實現中的性能挑戰。他山之石,根據老碼農的經驗,總結了一個導致系統性能失敗的原因列表。
1. 對最終用戶反饋的置若罔聞
作為最終用戶,才會意識到的現有潛在性能問題。為了理解生產系統中現有的性能問題,需要從最終用戶那里獲得關于應用程序在不同的預期負載條件下如何運行的持續反饋。總是有很多用戶在生產環境中使用某個功能,即使這一功能不能滿足他們期望的性能,他們也不會質疑它,而且會假設它是正確的,當用戶可以同時從多個位置訪問時,這可能是一個大問題。因此,如果想提高應用程序的性能,就必須讓最終用戶參與進來,以獲得關于應用程序或系統在生產環境中性能的持續反饋。當然,與最終用戶的交互需要時間和精力,盡管如此,為了使產品/應用提供最佳性能,這絕對是值得的。
2. 不關注性能目標
設定目標是確定系統性能的最重要方面之一。許多團隊經常無法實現他們的性能目標以求改進,于是花費了大量時間修復系統中現有的和隱藏的性能問題。性能測試的完美目標應該在最現實的條件下定義、設計和執行,比如真實的瀏覽器、設備和多個地理位置。確定正確的指標來監控,定義每個指標的最小閾值,執行性能測試來得到基線結果,所有這些數字對于確定什么樣的變化可以創造性能改進是必要的。在軟件開發生命周期中盡早開始性能測試是一種很好的做法,可以首先消除瓶頸,并確保在用戶負載很重的情況下不斷檢查應用程序的性能。
3. 不清晰及不完整的非功能性需求
收集完整的非功能性需求比功能性需求更復雜,因為它們被視為第二類甚至第三類需求。因此,它們經常被誤解和忽視,只有少數組織將非功能性需求作為一等公民。這會在系統架構/設計中導致嚴重的問題,經常導致項目崩潰和網站崩潰,使系統無法使用。在大多數情況下,非功能性需求文檔不完整、不一致,或者在大多數不成功的項目中不存在。性能測試第一步是對應用程序/系統進行可行性分析,并創建一組明確的非功能性需求。一個可靠的非功能性需求文檔將確定產品/應用具有最佳性能的所有標準。此外,還需要:
- 為產品/應用和系統建立明確的性能目標和期望
- 必須讓所有人(開發團隊、QA、管理團隊、 DBA、涉眾和業務團隊)達成一致。
- 在技術團隊、項目團隊和業務團隊之間建立溝通,以了解生產環境中最終用戶的實際性能問題
- 使用分析工具,獲取生產流量統計數據,以創建合適的工作負載模型
- 在收集非功能性需求時,了解應用程序/產品的體系結構、設計、問題和現有的性能問題
- 非功能性需求應該從軟件開發過程的開始并在整個生命周期中進行討論; 如果應用程序是全新的,基線和基準測試對于性能測試是必要的。
- 獲取所有涉及的內部和外部組件的完整信息,并了解它們如何通信(CDN、防火墻、 DNS、負載均衡器、服務器、網絡和系統、緩存等)
- 了解應用程序內存占用和第三方體系結構限制
- 與涉眾和業務團隊交談,以了解目標并確定什么是基本的、現有的遺留系統性能問題、平臺約束和競爭對手。
- 有必要記錄所有內容,并讓業務和其他涉眾一起參加會議,以確定現有的非功能性需求是否合適,并就定義的 SLA 達成一致。
4. 糟糕的架構設計
最初,糟糕的架構設計只會導致一些小問題,這些問題在開始時會比較少,但是會逐漸累積起來。簡單維護是一個挑戰,在一個區域中的任何更改都會破壞應用程序的其他部分。如果在架構設計階段作出了不恰當的決定,應用/系統可能會出現嚴重的性能下降,導致過多的網絡延遲和其他問題。由于不了解明確定義的系統架構,在負載測試執行階段會存在太多不確定性和復雜性的高風險,這可能會給性能測試和工程團隊帶來意想不到的性能問題。在軟件開發生命周期的應用程序設計和開發階段,由于性能方面的挑戰,軟件發布可能會推遲。
5. 對技術依賴缺乏預見
依賴關系是允許更多應用和功能組件之間的連接。特定的操作系統版本、應用服務器、數據庫服務器或 Java 虛擬機、通用語言運行庫和框架都是依賴關系的例子。然而,有些依賴關系更為復雜,比如由 Linux、 Java 中的各種包組成的依賴關系,以及 Python 和 Ruby 等腳本語言組成的依賴關系。理解每個技術在設計和基礎設施方面對每個組件的依賴性,使用哪些技術,以及使用哪些框架和工具來開發應用程序,對于系統性能來說,以期望的結果完成性能測試是至關重要的。
6.新功能的過度擴展
過度的新功能擴展是軟件開發人員經常遇到的一個主要障礙。處理這種情況的有效方法是定期舉行面向用戶體驗的會議和討論,每個團隊成員都參與其中,以驗證每個功能,并確保它有意義地解決了設定的問題。性能測試團隊必須從規劃發布的時間表開始,并且應該主動地公布需要的時間,以防在發布前的最后一分鐘添加任何新功能。如果項目有一個固定的最后期限,就需要提前計劃環境需求,以確保意外的環境延遲不會影響性能測試的進度。如果在最后一刻繼續添加了新功能,交付的質量大概率會受到影響。最終,客戶可能會拒絕最終的可交付成果,從而產生返工和額外資源短缺的情況。
7. 推崇好大喜功
在性能測試執行的最初版本中,直接關注目標 SLA 以達到可接受的限制可能是不現實的。性能測試是一個迭代過程,需要大量持續的性能測試來識別和消除所有的性能瓶頸。需要花費額外的時間優化每一行代碼和組件,以提高系統/應用程序的性能。在性能測試中,每個 SLA 和 KPI 都是必要的,并且只有通過持續的性能測試、代碼分析、內存分析、性能工程、監控以及客戶端和服務器端的調優才能獲得所需的響應時間、吞吐量、網絡延遲和資源利用率,這有時需要花費很長的時間。分析所有的性能結果和降低,并從用戶級、操作系統級、系統級、網絡級和服務器級使用適當的指標收集數據,對所有導致性能問題根本原因的分析是至關重要的。
8. 容量規劃的匱乏
許多基礎設施未能實施有效的規劃,簡單地說,容量規劃過程并不簡單直接。我們可以創建一個場景、添加流量、評估結果、解決性能問題,然后重復,直到滿意為止,但是實際的問題往往伴隨著糟糕的容量規劃。糟糕的容量計劃增加了性能缺失的可能性,風險會完全暴露,最終導致失敗。所有這些都可以通過仔細的容量規劃來適當解決。來自基礎設施領域的系統工程師、來自數據庫領域的DBA和來自應用程序開發領域的程序員是最需要參與有效容量規劃過程的三類人。許多人有時會將容量管理與容量計劃混淆,不能準確地預測和錯誤預測未來的工作負載。需要確保識別準確的資源需求(CPU、內存、磁盤空間和網絡帶寬) ,以支持當前和未來增加的工作負載,以滿足業務需求并避免容量規劃失敗。使用正確的度量標準進行持續監控將幫助我們進行有效的容量規劃,并且還有助于處理流量增加后未預料到的工作負載。
9. 性能問題沒有完全解決
當應用的用戶量增加時,往往會看到更多的性能問題。隨著時間的推移,系統中隱藏的性能問題和已知的性能問題是導致性能持續下降的主要原因。必須與項目中的每個團隊成員討論確定的每個瓶頸,以成功地確保客戶 SLA 的性能。當涉及到性能問題時,每一秒都很重要,如果忽略現有的性能問題,系統將會變慢,甚至更糟。例如,某些服務可能會停止在嚴重超載的服務器上運行,從而使應用程序無法訪問。找出監控數據,檢查服務的健康狀態,一般就能找出性能問題的常見原因。
10. 方法論的缺失
缺乏合適的方法來建立性能測試策略及其覆蓋范圍的話,會很難獲得有效的性能測試結果。理解性能測試方法和過程將幫助團隊中的每個工程師,特別是當性能問題出現時,為每個發生問題的瓶頸提供正確的修復。性能測試過程應該有良好的計劃和定義,并且文檔化。好的文檔可以在開發人員、 DBA和QA之間建立有效的溝通。隨著軟件變得更加復雜和多元化,并且有越來越多的平臺和位置需要測試,需要有一個強有力的性能測試方法,以確保正在開發的軟件系統經過充分的性能測試,以確保它們滿足特定的業務要求,并且能夠在所有預期的負載條件和環境中高性能地運行。