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