性能調優方法論:如何科學高效地定位性能問題?
一提起軟件系統中的性能問題,或許你首先想到的是 CPU 使用率過高或者內存占用率太大,進而致使程序執行速度變慢。此時,關注點往往只停留在軟件實現層面的性能調優上。實際上,這種以最小化資源占用為導向的性能優化,其核心目標是降低成本。
然而,對于產品來說,最為關鍵的其實是從客戶視角所關注的業務性能,比如用戶的平均響應時延、99% 的用戶響應時延分布等。這類性能優化的核心目標是提升用戶體驗,增強產品的行業競爭力。
但問題在于,在互聯網服務領域,從客戶視角去定位分析業務的性能問題存在一定挑戰,主要原因有兩點:
- 針對一些存在業務性能問題的場景,其系統內的服務或組件并不一定處于飽和狀態,所以無法直接從系統資源級監控中識別出問題。
- 如果只是個別服務或組件處于飽和狀態,往往可以通過彈性擴展來更快地提升性能體驗,所以這種情況也不是最棘手的性能問題。
再來看看嵌入式領域,以無線通信領域為例,存在很多業務性能優化非常苛刻的場景,如 FTP 下載速率優化、速度平穩沒有毛刺優化等。在這類系統的實現過程中,導致出現業務性能問題的原因會更多更復雜,問題可能發生在鏈路上的任何一個網元設備內,或者具體設備內的任何一個軟件組件或硬件單元上。因此,定位分析業務層性能問題的挑戰會更大。
事實上,定位分析業務的性能問題是很多程序員都很頭疼的問題。它需要你具備很高的業務能力,包括對業務流程的熟悉度、對軟件架構及軟件內實現邏輯的理解程度,甚至是對操作系統和硬件原理都要有深入的理解。不過,就我的實踐經驗來看,即使掌握了這些信息,如果沒有系統的定位分析方法的指導,依舊很難定位出性能問題。
所以,今天這節課我會給你分享一套性能調優方法論,帶你理解企業應用系統架構的整體邏輯和工作流程,在此基礎上了解引起性能問題的潛在軟硬件瓶頸點,最后介紹系統分析定位的方法。基于這個方法,當你再碰到比較棘手的業務性能問題時,就可以做到有的放矢,使用這套系統定位分析方法去解決真實的性能問題。
好了,下面我們就來了解下系統的整體架構。
系統架構視圖
為了能更好地分析與定位復雜的性能問題,你首先需要理解整個系統架構視圖,其核心主要包含這三層:產品業務模型、軟件系統架構、組件或服務實現,如下圖中所示:
圖片
產品業務模型:這是系統對外提供的業務功能與邏輯。以購物流程為例,其對外提供的功能邏輯為:瀏覽商品 —> 添加購物車 —> 查看庫存 —> 支付 —> 發快遞等。這實際上是站在用戶視角所感知到的與系統發生交互的過程。這個業務模型是軟件業務領域建模階段的重要產物,也是每個系統級產品都應包含的模型。
軟件系統架構:它表示的是整個軟件系統到具體組件或服務之間的拆分邏輯,以及組件或服務間的交互關系,如圖中的 A、B、C、E、F 等。這些軟件運行單元可以是一個微服務實例,也可以是一個組件實例,它們會通過通信與交互支撐實現復雜的業務功能。實際上,不管是嵌入式領域還是互聯網領域,軟件系統架構設計本質上都是對業務功能拆解的一個過程,通過拆分形成具有獨立清晰邊界的、更小的軟件運行單元。
組件或服務實現:這是組件或服務的內部代碼實現,它會依托于進程、內核、硬件的協作來完成核心的業務功能。我們知道,系統的業務性能是由硬件、操作系統、軟件實現以及之上的業務流程綜合決定的。當我們碰到業務性能問題時,會基于系統的架構視圖從上到下進行分析,最后總能找到具體的制約性能的瓶頸點。
那么,如果你可以提前認識軟硬件中常見的一些性能瓶頸點,了解它們對系統性能的影響,就能夠幫助你更加準確地分析業務性能問題。但是,很多程序員在定位性能問題時,喜歡只聚焦到某個點上持續優化,而這個點可能并不是性能瓶頸,所以最后很難有比較好的效果。那么,系統潛在的性能瓶頸點都有哪些呢?接下來,我們就一起來看看。
潛在的性能瓶頸點
首先,一般來說,性能瓶頸通常是由一些關鍵資源使用過度所引起的,并且不同資源使用到達瓶頸(飽和)狀態對性能產生的影響和規律各不相同。在計算機系統中,每種硬件資源,如 CPU、Cache、內存、磁盤、網絡接口、總線等,都有可能成為性能瓶頸。這是因為當硬件處理到達飽和狀態時,會直接導致硬件上的軟件運行性能下降,最終使得業務性能受到影響。
相比之下,軟件實現所導致的性能問題及影響很容易被忽略。所以今天,我會重點介紹由于軟件實現而引起業務性能問題的瓶頸點,以便在你分析業務性能問題的過程中,更好地識別和發現這些問題。
串行資源受限
第一類典型的瓶頸問題是串行資源(或互斥資源),這是一種可能觸發業務性能問題的軟件實現方式。下圖為串行資源的擴展對性能影響的模型圖,它展示了隨著業務規模的擴大,對性能所造成的影響。
圖片
如圖中左側所示,由于串行資源是有限的,隨著業務請求量的增加,當資源使用飽和后,會導致請求處理吞吐量到達峰值后便無法再提升。同時,如圖的右側所示,當串行資源使用飽和后,平均處理時延也會因排隊或者阻塞而不斷拉長。在軟件實現中,對性能影響較大的串行資源種類有很多,從粒度從小到大可以包括:互斥鎖、并行設計中的串行部分、系統依賴的不可擴展的服務或接口等,它們都有著相似的影響。但需要注意的是,在業務場景中,還有不少資源數目是大于等于 2 的情況,比如線程池、數據庫連接池、其他不能無限擴展的服務或接口。這種有限軟件資源的場景,它們對性能的影響與串行資源對性能的影響較為類似,所以同樣可以參考串行資源對性能影響的分析視圖。
緩沖類資源消息溢出
第二種容易引發性能問題的軟件實現是緩沖類資源,像緩沖區、消息隊列、消息中間件等都歸屬于緩沖類資源。緩沖技術能夠實現削峰填谷的機制,從而平滑上游和下游處理速度之間的差異。如下圖所示,倘若緩沖區設置過小,當上游請求到達峰值時,可能會致使部分請求被阻塞或者丟棄,進而影響到業務性能。而如果緩沖區設置得越大,其實現削峰填谷的能力就會更強。
但如果緩沖區設置得過大,也會造成內存資源的浪費,所以緩沖區大小設置對性能的影響也很關鍵。
緩存命中率過低
緩存技術在軟件實現層面是一項重要的性能優化手段,同時也可能成為影響業務性能的潛在因素。我們了解到,在緩存的使用中有一個關鍵指標,即緩存命中率,其計算公式為緩存命中個數除以(緩存命中個數與緩存未命中個數之和)。這個指標對業務性能的影響如下圖所示
圖片
軟件 Bug
最后,軟件實現中存在一個對性能有著極大影響的因素 —— 軟件 Bug。在以往對業務性能問題進行定位分析的過程中,由軟件 Bug 導致的性能問題并不在少數。例如,代碼本應是批處理操作,卻因處理錯誤退化為循環調用;又或者在運用緩存技術時,由于緩存 Key 構造錯誤,使得緩存永遠無法命中,進而引發業務性能驟然下降等情況。
然而,看到這里,你或許會產生疑問:是不是所有的業務性能問題都是由軟硬件層面的資源性能瓶頸所觸發的呢?在我看來,并非如此。有些性能問題可能源于業務模型或者流程本身的問題,軟件和硬件僅僅是其載體。例如,業務中的某些限速策略會致使處理性能受到限制。另外,在一些更為復雜的系統業務設計中,也可能會引入性能問題,這就如同設計不合理的十字路口紅綠燈一般,會導致嚴重的擁堵狀況。不過,對于這種因業務模型等因素引發的性能問題,我們其實可以通過調整紅綠燈時間,也就是調整軟件不同模塊的業務職責和接口實現,從而顯著改善擁堵現象。
總而言之,在軟件實現的過程中,可能引發潛在性能問題的因素眾多。鑒于此,我們需要系統的分析定位方法作為指導,否則將很難準確識別出系統中的所有性能瓶頸點。
所以接下來,我們就一起探討下這個系統分析定位方法吧。
系統分析定位法
實際上,用于分析定位性能問題的方法有不少。像 USE 方法,也就是從檢查各類資源、觀察其使用率飽和的角度去探尋可能存在的性能瓶頸;還有從下往上逐步分析系統中資源使用指標的方法來查找性能瓶頸。另外,還有隨機變動訛方法(這是一種先隨機猜測再進行驗證的方法)、科學實驗法等等。當面對特定的性能問題時,或許每種定位分析方法的效果都不一樣。不過呢,今天我要向你介紹的這種方法,是我依據以往分析各類性能問題所積累的經驗總結出來的一種方法思路。它相對比較系統,而且效率較高,當你在遭遇各種業務領域的性能問題時,都可以運用這種方法。具體如下圖所示。
圖片
整個定位分析方法從上到下分為三層,分別是業務模型分析、軟件架構分析以及組件或服務實現分析。下面逐一為你介紹。
一、業務模型分析
業務模型分析的目標是找出引發業務性能問題的業務觸發點,并對分析的正確性進行驗證。越是復雜的業務模型,導致業務性能問題出現的根本原因可能就越難以察覺。如果在業務模型分析中確定的根本原因不準確,那么后續投入再多精力進行深入分析也將是徒勞無功。例如,在分析 TCP 流量下降的性能問題時,可能是下行鏈路出了問題,也可能是上行鏈路存在問題。如果上行鏈路延遲增大,導致 ACK 反饋不及時,進而觸發擁塞控制,使得 TCP 流量不高。在這種情況下,即便在下行鏈路上花費巨大精力去分析,也不會有任何效果。所以,驗證業務層性能問題根因分析的結論是否正確十分必要。在此,我建議你可以通過打樁的方式暫時規避根因觸發點,觀察性能問題是否有所改善,以此作為有效的驗證手段。當然,不同系統的業務模型差異很大,所以業務模型沒有通用的方法或規律可循,你只能憑借對業務邏輯的深入理解,并依據業務層實現的運行狀態監控信息來進行分析。當完成業務模型分析后,你會發現導致性能問題的原因可能是由某個具體的業務流程引起的。這時,你就可以針對這個具體業務流程,深入到軟件架構中進一步分析。
二、軟件架構分析
在軟件架構分析中,我們主要依靠軟件架構中組件或服務的接口交互關系來進行分析。通常對于大型的系統級產品來說,組件或服務間接口的交互信息一定是可以被監控、獲取并進行分析的。這樣,根據獲取的接口交互監控信息,我們能夠找到觸發業務性能問題的具體組件或服務。此外,和業務模型分析一樣,我們在軟件架構分析階段識別出的存在性能瓶頸的組件或服務,也需要進一步驗證。只有在確保分析結果正確后,才能進行下一階段的深入分析。我以前在通信領域從事性能問題分析時,每個子系統組件都是由不同的團隊開發維護的。當面對復雜的業務性能問題時,我需要沿著子系統組件的接口邊界逐步排查分析,將性能問題交接給下一個子系統組件,并提供充足的分析與驗證信息。但即使在這樣的情況下,仍然可能出現分析錯誤導致返工的情況。所以這一點你一定要注意。
三、軟件內部分析
事實上,在互聯網業務領域分析性能問題時,無論是業務模型分析階段還是軟件架構分析階段,驗證分析結論正確性的過程都很容易被我們忽視,從而導致性能問題分析定位出現返工或錯誤。根據我的實踐經驗,當定位到具體的某個組件存在性能瓶頸時,我們就需要深入到這個組件內部去分析其具體實現,查看這個組件是否存在之前提到的性能瓶頸點,比如串行資源、緩存、軟件 Bug 等,并根據分析結果給出優化建議。最后,當所有的性能瓶頸點都被解決后,你還需要再次驗證性能問題是否得到改善。如果沒有改善,那么你可能需要重新審視分析過程,或者尋找其他可能的性能瓶頸點。
如何在真實的數據分析業務中應用這套方法論?
這是我曾經處理在線數據分析業務中碰到的真實性能問題,當時產品有部分用戶投訴,在 Web 頁面中的查詢數據下載功能性能很差,造成用戶等待時間長。而我采用的就是這套性能定位方法,具體定位過程如下圖所示:
圖片
第一階段:進行業務模型分析,以識別出存在性能問題的業務流程。在互聯網服務領域,許多業務的性能問題是由用戶發現的,然而在其他業務領域中,業務性能瓶頸點則需要依靠業務領域的監控統計,并結合業務模型共同分析才能識別出來。就這個案例而言,系統中可能包含眾多的業務流程。在業務模型分析階段,我們確定了存在性能問題的業務流程為 “查詢數據下載功能”。具體的用戶業務流程是:先選擇查詢條件,接著查詢返回數據,然后生成壓縮數據,再上傳至對象存儲,最后生成下載鏈接。之后,我們便可以依據這個業務流程,去尋找并定位那些引入性能瓶頸的組件和服務。
第二階段:處于軟件架構分析階段時,我們能夠根據存在性能問題的業務流程,找到由軟件導致性能瓶頸的組件和服務。在這個階段,主要運用系統的微服務間的接口日志進行分析,主要基于 Elasticsearch+Kibana 工具,沿著業務請求接口鏈路去尋找具體的組件或者服務,最終將性能問題定位到一個確定的微服務組件中。
第三階段:進行組件或服務內實現分析。在此階段,深入到導致性能問題的微服務中,通過查看內部實現的相關監控或統計信息,發現導致性能問題的原因是:壓縮數據處理與瀏覽統計邏輯使用了相同的計算任務隊列。由于之前的突發瀏覽業務,使得隊列中積攢了許多待處理的瀏覽統計任務,進而導致壓縮數據處理任務被排隊阻塞,時延變長。這樣一來,經過仔細分析后我們會發現,因為用戶無法感知到瀏覽統計邏輯,而壓縮數據處理對用戶來說卻比較敏感,所以在這里使用同一個任務隊列,就造成了非關鍵業務邏輯對核心業務的處理時延產生了影響。