最近看了zee老弟的文章,通過分析網絡流量來分析性能問題,于是也想寫一篇。
我早期做性能測試,大概在99年。給一個銀行做性能測試,因為其中很大的一個部分是我們開發的。于是自己寫了一個程序,來給后臺系統加壓。
大概在2001年,我們做了兩外一個系統,跑在aix上面,性能很差,我幫開發團隊去看一下問題,結論是調度過度,架構不合理(組件模塊劃分的過細)。調優之后,性能提升了大概100倍。后來去給客戶做poc,客戶還嫌慢,說明調優還不到位。再后來又做了一次調優,性能才正常。所謂的正常,就是跟使用tuxedo相比,基本上性能持平,一個數量級。
從性能問題來看,大概分成幾種情況:1,網絡帶寬問題;2,某個節點處理能力(就是tps差)不行;3,流量配置不合理;4,鏈路設計問題。
先說網絡帶寬問題。以前的老系統,特別是銀行的,一般情況下oltp都不會有帶寬問題,因為根據oltp的標準,一個請求包在1-2k,響應報文在4k之內,除非線路很差,一般都不會有。從現在的情況來看,更不會有網絡問題。
我遇到一次網絡問題,是由于病毒占用了大量的帶寬,阻塞了。特殊的情況在于報表下載。如果所有的用戶,在某個時間點上都下載報表呢?也會有擁堵。
實際上,只要根據tps和一次請求占用的流量大小,來計算一下,就知道整個的帶寬是不是有問題。
比如,一次請求的數據,假設是50k,tps是1000,那么帶寬需求是:1000*50k=50M。還要考慮上行帶寬還是下行帶寬,請求是上行帶寬。
此外就是一些網絡上傳輸的圖片很容易占用帶寬。
再說流量分配不合理。某個客戶有多個節點,使用nginx來做負載均衡,由于配置錯誤,導致90%以上的流量都分配到其中一個節點,導致性能嚴重不達標。這種就需要使用全鏈路分析,看兩個不同節點的cpu占用、帶寬,很容易發現問題。流量分配不合理,主要是配置問題。因此全鏈路跟蹤監控工具非常重要。
近些年,由于系統越來越復雜,已經從C/S、B/S架構的兩層結構,發展到三層結構、多層結構。
在業務處理的每一層,如果出現問題,都可能出現性能瓶頸,所以,我們首先要定位,是哪一層出現了問題。
鏈路設計問題。有時候,由于應用系統設計不當,導致產生了很多多余的鏈路。比如可以使用三次通訊來解決的問題,結果使用了5次,多出來的兩次很容易造成錯誤和性能問題。當然性能測試只能夠發現問題,解決問題還要看設計鏈路的人。
這里面就涉及到一個問題:架構。網絡架構、系統架構、IT架構等等。話題太大,就不展開贅述了。
最后,我們看節點處理能力問題。其實,節點又分成很多種類,比如存儲、比如數據庫。這一類的問題,一個要看數據庫的配置和資源情況,另外一個就要看表結構、索引,重要的一點是程序。
數據庫問題,常用的是看資源是否占滿,比如io,比如cpu等資源是否過高。如果不高,但是又很慢,大多數是程序和結構問題。
最后看代碼,也就是應用程序。應用程序優化,往往是系統的核心,絕大多數的性能問題,都是由于代碼編寫不當引起的。
從我自己的經驗來看,主要是幾大類:
1,錯誤的數據結構和算法。
某個項目,做了一個插入操作,結果花費了一分鐘。我仔細看了一下代碼,其實算法并不是很復雜,就是在數據庫中構建了一個tree,然后把某個節點插入。
但是很慢。本質的問題在于,程序員把數據庫當作內存來使用。內存的訪問速度很快,數據庫查了幾個量級。
所以使用錯誤的數據結構,是很多問題的核心。這種情況就需要修改架構和算法才能夠解決。
2,算法問題。
另外一個項目,也是操作很慢。去看了一下,沒有架構問題。但是,有很多循環嵌套。關鍵是,在循環里面去訪問database。
千萬不要在循環里面去訪問db,幾乎是百分之百的慢。
循環嵌套。就是多層循環,里面還嵌套數據庫訪問,程序員是想作死。
3,block和輪詢。
block,阻塞和輪詢,是我們訪問資源的兩個方式。block的問題會造成程序掛起,但是掛起并不消耗cpu,但是會占住一個線程/進程。
輪詢很快,但是頻繁的輪詢會導致cpu上升。
所以要評估你的算法,當訪問資源的時候,是使用block還是輪詢。
好像這一直是個問題,需要大量編碼經驗才能解決。
這也就是說,為什么沒有大量的編碼經驗,吹噓做架構師,很容易犯低級錯誤。
4,資源忘了釋放。
這是很多板磚程序員容易犯的錯。
5,分清楚系統調用和一般的調用。
系統調用,system call,會調用操作系統的核心,訪問核心資源。所以,你看起來是一個函數,但是這個函數會導致你的系統很慢。
當然現在使用的語言遠比c這樣原始的語言高級,使得程序員分不清系統調用和一般函數。
經常遇到的問題是,內存分配。當你頻繁訪問內存,一些算法是從操作系統的堆來申請內存的,導致系統很慢,而且會產生很多內存碎片。
所以分清楚系統調用和一般函數,非常重要,盡量避免使用系統調用,特別是頻繁的調用。
6,程序執行效率不高。
這個其實有很多算法,比如循環展開等等。你需要去了解編譯器、cpu的指令序列是如何工作的。
cpu最怕的指令是jump,就是程序里面的循環和判斷(if-else)。
如果知道這些,解決大多數性能問題應該不困難。
推薦閱讀