一種進(jìn)行系統(tǒng)性能定位的簡單策略
性能問題往往是復(fù)雜和神秘的,可能根本沒有或很少提供關(guān)于其起源的線索。在沒有起點(diǎn)或者沒有提供方法的情況下,性能問題通常是隨機(jī)分析的: 猜測問題可能在哪里,然后改變事情,直到問題消失。如果我們猜得沒錯的話,雖然這可能會有結(jié)果 ,但它也可能會耗費(fèi)大量時間或者具有破壞性,并可能最終忽視某些問題。
關(guān)于系統(tǒng)性能的那些問題
典型系統(tǒng)中組件的數(shù)量龐大,系統(tǒng)的性能分析是復(fù)雜的。一個環(huán)境可以由數(shù)據(jù)庫、 Web 服務(wù)器、負(fù)載均衡器和定制應(yīng)用程序等組成,所有這些都運(yùn)行在操作系統(tǒng)上(裸機(jī)或虛擬機(jī))。這還只是軟件而已,硬件和固件,包括外部的存儲系統(tǒng)和網(wǎng)絡(luò)基礎(chǔ)設(shè)施,向環(huán)境中添加了更多的組件,其中任何組件都是潛在的問題根源。每一個組件都可能需要自己的專業(yè)領(lǐng)域,而且公司往往沒有了解其環(huán)境中所有組件的員工。
性能問題還可能來自組件之間的復(fù)雜交互,這些交互可以很好地獨(dú)立工作,解決這類問題可能需要多個領(lǐng)域的專家共同努力。
另一個復(fù)雜的因素是,性能的好壞可能是主觀的: 一個用戶不能接受的延遲對另一個用戶可能是可以接受的。如果沒有辦法清楚地確定問題,不僅很難知道問題是否存在,而且很難知道問題何時得到解決。衡量性能問題的能力需要對這些問題能夠量化,并根據(jù)重要性對不同問題進(jìn)行排序。
性能分析方法可以提供一種有效的方法來分析系統(tǒng)或組件并識別問題的根本原因,而不需要深入的專業(yè)知識。方法論也可以提供識別和量化問題的方法,使它們被了解和排序。特定的性能檢查表已經(jīng)成為一種流行的資源。然而,可觀測性僅限于列表中的特定項(xiàng)目,它們通常是過時且需要更新的。這些檢查列表可能關(guān)注了那些可以很容易記錄的已知問題,比如可調(diào)參數(shù)的設(shè)置,但不包括對源代碼或環(huán)境的定制補(bǔ)丁。
既然如此,出現(xiàn)了關(guān)于性能問題的常見現(xiàn)象。
關(guān)于系統(tǒng)性能的反方法論
第一種現(xiàn)象是『甩鍋』,常見的方式:
- 找到一個自己不負(fù)責(zé)的系統(tǒng)或環(huán)境組件。
- 假設(shè)問題出在那個組件上。
- 將問題轉(zhuǎn)向負(fù)責(zé)任的團(tuán)隊(duì)。
- 如果被證明是錯誤的,回到第一步。
例如,“也許是網(wǎng)絡(luò)的問題。你能不能和網(wǎng)絡(luò)團(tuán)隊(duì)核實(shí)一下,看看他們是否丟失了數(shù)據(jù)包之類的東西?”這種方法不是調(diào)查性能問題,而是把它們變成別人的問題,這極可能會浪費(fèi)其他團(tuán)隊(duì)的資源。由于缺乏數(shù)據(jù)分析,甚至從一開始就缺乏數(shù)據(jù),導(dǎo)致了這一假設(shè)。
第二種方式是運(yùn)行工具和收集數(shù)據(jù),這要優(yōu)于隨意的假設(shè),但它仍不足以進(jìn)行有效的性能分析,這是缺乏深思熟慮的方法。用戶通過選擇熟悉的、在互聯(lián)網(wǎng)上發(fā)現(xiàn)的或隨機(jī)發(fā)現(xiàn)的可觀測性工具來分析性能,然后看看是否有任何明顯的跡象出現(xiàn)。這種隨機(jī)應(yīng)變的方法可能會忽略許多類型的問題。
找到合適的工具需要一段時間,最熟悉的工具會首先運(yùn)行,即使它們不是最有意義的。學(xué)習(xí)更多的工具有所幫助,但仍然是一個有限的方法。由于缺乏可觀察性工具或指標(biāo),某些系統(tǒng)組件或資源可能會被忽略。此外,我們可能沒有意識到視圖是不完整的,沒有辦法識別“未知的未知”。
現(xiàn)有的性能分析方法
可以使用更好的性能分析方法,在運(yùn)行工具之前可以解決問題,包括問題陳述方法、負(fù)載塑造法和鉆取分析法。
問題陳述法
客服或者支持人員收集問題信息時通常使用問題陳述法,可以用于性能分析。其目的是收集問題的詳細(xì)描述以指導(dǎo)更深入的分析,這個描述本身甚至可以解決這個問題。這通常是通過詢問以下問題進(jìn)入分析環(huán)節(jié):
- 什么會被認(rèn)為存在性能問題?
- 這個系統(tǒng)曾經(jīng)運(yùn)行良好嗎?
- 最近系統(tǒng)有什么變化? (軟件? 硬件? 負(fù)載?)
- 性能下降是否可以用延遲或執(zhí)行時間來表示?
- 這個問題是否影響到其他人或應(yīng)用程序(或者只是影響到自己) ?
- 環(huán)境是什么? 使用什么軟件和硬件? 版本? 配置?
這些問題可以根據(jù)具體場景進(jìn)行定制。這樣的問題看起來很明顯,答案往往也能解決了一類問題,不需要更深入的方法。當(dāng)情況不是這樣時,可以調(diào)用其他方法來提供服務(wù),包括負(fù)載塑造法和鉆取分析法。
負(fù)載塑造法
可以是有屬性的,例如:
- 負(fù)載是誰引起的? 進(jìn)程 ID、用戶 ID、遠(yuǎn)程 IP 地址?
- 為什么要產(chǎn)生異常負(fù)載? 可能的代碼路徑?
- 負(fù)載的其他特征是什么? IO、吞吐量、類型?
- 負(fù)載是如何隨著時間變化的?
這些問題有助于將負(fù)載問題與架構(gòu)問題分離開來。最好的性能往往來自于消除不必要的工作。有時,這些瓶頸是由應(yīng)用程序故障(例如,線程卡在循環(huán)中)造成的,也可能是由于錯誤配置產(chǎn)生的。通過維護(hù)或重新配置,這些不必要的工作可以被消除,負(fù)載塑造可以識別這類變更問題。
鉆取分析法
鉆取分析包括剝離軟件和硬件的層次,以找到問題的核心,從高到低深入到不同層次的細(xì)節(jié)。這些更深入的細(xì)節(jié)甚至包括檢查內(nèi)核的內(nèi)部構(gòu)造,例如,通過對內(nèi)核堆棧跟蹤進(jìn)行取樣分析,或者通過動態(tài)跟蹤檢查內(nèi)核函數(shù)的執(zhí)行。
鉆取分析法包括:
- 監(jiān)測,不斷地記錄許多系統(tǒng)隨時間變化的高級統(tǒng)計(jì)數(shù)據(jù),如果出現(xiàn)問題,則識別或發(fā)出警報(bào)。
- 識別,如果系統(tǒng)存在疑似問題,這將調(diào)查范圍縮小到使用系統(tǒng)工具和識別可能瓶頸的特定資源或感興趣的領(lǐng)域。
- 分析,進(jìn)一步審查特定的系統(tǒng)領(lǐng)域,找出根本原因,并將問題量化。
分析階段可以向下鉆取,從軟件堆棧頂部的應(yīng)用程序開始,向下鉆取到系統(tǒng)庫、系統(tǒng)調(diào)用、內(nèi)核內(nèi)部、設(shè)備驅(qū)動程序和硬件。雖然向下鉆取分析常常能夠確定問題的根本原因,但是這樣做可能會耗費(fèi)時間,而且當(dāng)向錯誤的方向鉆取時,可能會浪費(fèi)大量的時間。
有沒有更高效的方法么?
關(guān)于性能問題的早期快速定位
對于每個資源,我們可以檢查它的利用率、飽和度和錯誤。資源意味著單獨(dú)檢查的所有物理服務(wù)器功能組件(cpu、磁盤、總線等),一些軟件資源也可以使用相同的方法進(jìn)行檢查。
利用率是資源在特定時間間隔內(nèi)工作時間的百分比。在忙時,資源可能仍然能夠接受更多的負(fù)載, 具體與否可以通過飽和度來確定。對于某些資源類型,例如內(nèi)存,利用率是所使用資源的容量,這與基于時間的定義不同。一旦容量資源達(dá)到100% 的利用率,要么將負(fù)載(飽和度)排入隊(duì)列,要么返回錯誤。錯誤是指錯誤事件的數(shù)量,當(dāng)故障模式是可恢復(fù)的時候,它們可能不會立即被注意到。這包括失敗和重試的操作,以及在冗余設(shè)備池中失敗的設(shè)備。
嘗試迭代系統(tǒng)資源,而不是從工具開始,創(chuàng)建一個要問的問題完整列表,只搜索用于回答這些問題的工具。即使找不到回答這些問題的工具,也是極其有用的,它們現(xiàn)在變成“已知的未知”。
嘗試指向有限數(shù)量的關(guān)鍵指標(biāo),以便盡可能快地檢查所有系統(tǒng)資源。在此之后,如果沒有發(fā)現(xiàn)問題,可以轉(zhuǎn)向其他方法。
度量指標(biāo)
度量指標(biāo)包括:
- 利用率:一個時間間隔內(nèi)的百分比(例如,一個 CPU 的利用率為90%)。
- 飽和度:等待隊(duì)列長度(例如,CPU的平均運(yùn)行隊(duì)列長度為4)。
- 錯誤報(bào)告中的錯誤數(shù)量(例如,最后50次網(wǎng)絡(luò)交互的沖突)。
表示測量的時間間隔也很重要。雖然看起來有些違反直覺,即使在較長的時間間隔內(nèi)總利用率很低,但短時間的高利用率會導(dǎo)致性能問題。例如,CPU 利用率在秒級可能有很大的差異,五分鐘內(nèi)的平均利用率會掩蓋達(dá)到100% 的短時間段內(nèi)的飽和度問題。
資源列表
快速定位性能問題需要一個完整的資源列表,例如,一個服務(wù)器硬件資源的通用列表如下:
- CPU ー sockets、核心、硬件線程(虛擬 cpu)。
- 內(nèi)存ー DRAM
- 網(wǎng)絡(luò)接口ー以太網(wǎng)口
- 儲存ー磁盤
- 控制器ー存儲、網(wǎng)絡(luò)。
每個組件通常是單個資源類型。例如,主存是容量資源,網(wǎng)絡(luò)接口是 I/O 資源,可以用 IOPS 或吞吐量來度量。有些組件可以表現(xiàn)為多種資源類型ー例如,存儲設(shè)備既是 I/O 資源又是容量資源,需要考慮所有可能導(dǎo)致性能瓶頸的類型。需要注意的是,I/O 資源可以進(jìn)一步抽象為排隊(duì)系統(tǒng),對這些請求進(jìn)行排隊(duì),然后為其提供服務(wù)。
高利用率或高飽和度下導(dǎo)致性能瓶頸的資源是最值得關(guān)注, 而緩存在高利用率下提高性能。在排除系統(tǒng)瓶頸之后,可以檢查緩存命中率和其他性能屬性。如果不能確定是否要包含一個資源,就包含它,然后看看這個度量指標(biāo)在實(shí)踐中工作得如何。
功能模塊圖
一種遍歷資源的方法是查找或繪制系統(tǒng)的功能模塊圖。這種類型的圖表顯示了資源之間的關(guān)系,這在尋找數(shù)據(jù)流中的瓶頸時非常有用。在確定各種總線的利用率時,在功能圖上用其最大帶寬標(biāo)注每個總線。在進(jìn)行單一測量之前,可以根據(jù)功能模塊圖來探查系統(tǒng)瓶頸。
CPU、內(nèi)存和 I/O 的互連接性常常被忽略。幸運(yùn)的是,它們通常不是導(dǎo)致系統(tǒng)瓶頸的原因。不幸的是,當(dāng)它們出現(xiàn)時,問題可能很難解決,或許需要可以升級主板或減少負(fù)載。
度量方法
一旦獲得了資源列表,需要考慮每個資源所需的度量類型(利用率、飽和度和錯誤數(shù)量)。這些指標(biāo)可以表示為每個時間間隔的平均值或者計(jì)數(shù)。
注意當(dāng)前那些不可用的指標(biāo):,這些“已知的未知”最終將得到一個包含大約幾十個指標(biāo)的列表,其中有些很難度量,有些則根本無法度量。幸運(yùn)的是,最常見的問題通常出現(xiàn)在更簡單的指標(biāo)上,例如,CPU 飽和度、內(nèi)存容量飽和度、網(wǎng)絡(luò)接口利用率、磁盤利用率等 ,因此可以先檢查這些指標(biāo)。
其中一些指標(biāo)可能無法從操作系統(tǒng)工具中獲得,必須使用DTrace或 CPU 性能工具編寫自己的軟件來獲得這些指標(biāo)。
軟件資源
一些軟件資源也可以進(jìn)行類似的檢查,通常適用于較小的軟件組件,而不適用于整個應(yīng)用程序。例如:
- 互斥鎖。利用率可以定義為鎖被持有的時間,飽和度是鎖等待的線程排隊(duì)。
- 線程池。利用率可以定義為線程忙于處理工作的時間,飽和度可以定義為等待線程池處理的請求數(shù)量。
- 進(jìn)程/線程容量。系統(tǒng)可能有數(shù)量受限的進(jìn)程或線程,其當(dāng)前使用可定義為利用率; 等待分配可能表明飽和度; 當(dāng)分配失敗時發(fā)生錯誤。
- 文件描述符容量,與上面的類似。
如果可以正常度量,就可以使用這些指標(biāo); 否則,軟件故障排除可以留給其他方法。
性能定位的策略
性能問題定位的核心是確定使用哪些度量指標(biāo),從操作系統(tǒng)讀取這些指標(biāo)后,需要解釋這些指標(biāo)當(dāng)前的值。對于某些度量指標(biāo),解釋可能是顯而易見的,并且有很好的文檔記)。如果不明顯的指標(biāo),可能取決于工作量需求或?qū)λ麄兊念A(yù)期。錯誤排在第一位,因?yàn)樗鼈兺ǔ1壤寐屎惋柡投雀菀住⒏斓剡M(jìn)行解釋。
不幸的是,一個系統(tǒng)可能會遇到不止一個性能問題,首先要完成標(biāo)準(zhǔn)動作, 檢查資源表并列出所有發(fā)現(xiàn)的問題,然后根據(jù)可能的優(yōu)先級對每個問題進(jìn)行調(diào)查會更有效。
小結(jié)
系統(tǒng)性能分析可能是復(fù)雜的,任何組件都可能產(chǎn)生問題,包括它們之間的交互。常用的方法有時類似于猜測,嘗試熟悉的工具或者在沒有確鑿證據(jù)的情況下提出假設(shè)。我們可以執(zhí)行一種簡單策略,對完整的系統(tǒng)進(jìn)行健康檢查。考慮所有的資源,以避免忽略問題,使用有限的度量,以便能夠迅速遵循,這對于分布式環(huán)境(包括云計(jì)算)尤其重要。