1. 程式人生 > >33、 後臺服務出現明顯“變慢”,談談你的診斷思路?

33、 後臺服務出現明顯“變慢”,談談你的診斷思路?

在日常工作中,應用或者系統出現效能問題往往是不可避免的,除了在有一定規模的 IT 企業或者專注於特定效能領域的企業,可能大多數工程師並不會成為專職的效能工程師,但是掌握基本的效能知識和技能,往往是日常工作的需要,並且也是工程師進階的必要條件之一,能否定位和解決效能問題也是對你知識、技能和能力的檢驗。

今天我要問你的問題是,後臺服務出現明顯“變慢”,談談你的診斷思路?

典型回答

首先,需要對這個問題進行更加清晰的定義:

  •   服務是突然變慢還是長時間執行後觀察到變慢?類似問題是否重複出現?
  •   “慢”的定義是什麼,我能夠理解是系統對其他方面的請求的反應延時變長嗎?


第二,理清問題的症狀,這更便於定位具體的原因,有以下一些思路:

  •   問題可能來自於 Java 服務自身,也可能僅僅是受系統裡其他服務的影響。初始判斷可以先確認是否出現了意外的程式錯誤,例如檢查應用本身的錯誤日誌。對於分散式系統,很多公司都會實現更加系統的日誌、效能等監控系統。一些 Java 診斷工具也可以用於這個診斷,例如通過 JFR(Java Flight  Recorder),監控應用是否大量出現了某種型別的異常。如果有,那麼異常可能就是個突破點。如果沒有,可以先檢查系統級別的資源等情況,監控 CPU、記憶體等資源是否被其他程序大量佔用,並且這種佔用是否不符合系統正常執行狀況。
  •   監控 Java 服務自身,例如 GC 日誌裡面是否觀察到 Full GC 等惡劣情況出現,或者是否 Minor GC 在變長等;利用 jstat 等工具,獲取記憶體使用的統計資訊也是個常用手段;利用 jstack 等工具檢查是否出現死鎖等。
  •   如果還不能確定具體問題,對應用進行 Profiling 也是個辦法,但因為它會對系統產生侵入性,如果不是非常必要,大多數情況下並不建議在生產系統進行。
  •   定位了程式錯誤或者 JVM 配置的問題後,就可以採取相應的補救措施,然後驗證是否解決,否則還需要重複上面部分過程。


考點分析

今天我選擇的是一個常見的並且比較貼近實際應用的的效能相關問題,我提供的回答包括兩部分。

  •   在正面回答之前,先探討更加精確的問題定義是什麼。有時候面試官並沒有表達清楚,有必要確認自己的理解正確,然後再深入回答。
  •   從系統、應用的不同角度、不同層次,逐步將問題域儘量縮小,隔離出真實原因。具體步驟未必千篇一律,在處理過較多這種問題之後,經驗會令你的直覺分外敏感。


大多數工程師也許並沒有全面的效能問題診斷機會,如果被問到也不必過於緊張,你可以向面試官展示診斷問題的思考方式,展現自己的知識和綜合運用的能力。接觸到一個陌生的問題,通過溝通,能夠條理清晰地將排查方案逐步確定下來,也是能力的體現。

面試官可能會針對某個角度的診斷深入詢問,兼顧工作和麵試的需求,我會針對下面一些方面進行介紹。目的是讓你對效能分析有個整體的印象,在遇到特定領域問題時,即使不知道具體細節的工具和手段,至少也可以找到探索、查詢的方向。

  •   我將介紹業界常見的效能分析方法論。
  •   從系統分析到 JVM、應用效能分析,把握整體思路和主要工具。對於執行緒狀態、JVM  記憶體使用等很多方面,我在專欄前面已經陸陸續續介紹了很多,今天這一講也可以看作是聚焦效能角度的一個小結。


如果你有興趣進行系統性的學習,我建議參考 Charlie Hunt 編撰的《Java Performance》或者 Scott Oaks 的《Java 
Performance:The Definitive Guide》。另外,如果不希望出現理解偏差,最好是閱讀英文版。

 

知識擴充套件

首先,我們來了解一下業界最廣泛的效能分析方法論。

根據系統架構不同,分散式系統和大型單體應用也存在著思路的區別,例如,分散式系統的效能瓶頸可能更加集中。傳統意義上的效能調優大多是針對單體應用的調優,專欄的側重點也是如此,CharlieaHunt 曾將其方法論總結為兩類:

  •   自上而下。從應用的頂層,逐步深入到具體的不同模組,或者更近一步的技術細節單元,找到可能的問題和解決辦法。這是最常見的效能分析思路,也是大多數工程師的選擇。
  •   自下而上。從類似 CPU  這種硬體底層,判斷類似Cache-Miss之類的問題和調優機會,出發點是指令級別優化。這往往是專業的效能工程師才能掌握的技能,並且需要專業工具配合,大多數是移植到新的平臺上,或需要提供極致效能時才會進行。


例如,將大資料應用移植到 SPARC 體系結構的硬體上,需要對比和儘量釋放效能潛力,但又希望儘量不改原始碼。

我所給出的回答,首先是試圖排除功能性錯誤,然後就是典型的自上而下分析思路。

 

第二,我們一起來看看自上而下分析中,各個階段的常見工具和思路。需要注意的是,具體的工具在不同的作業系統上可能區別非常大。

系統性能分析中,CPU、記憶體和 IO 是主要關注項。

對於 CPU,如果是常見的 Linux,可以先用 top 命令檢視負載狀況,下圖是我擷取的一個狀態。


可以看到,其平均負載(load average)的三個值(分別是 1 分鐘、5 分鐘、15 分鐘)非常低,並且暫時看並沒有升高跡象。如果這些數值非常高(例如,超過 50%、60%),並且短期平均值高於長期平均值,則表明負載很重;如果還有升高的趨勢,那麼就要非常警惕了。

進一步的排查有很多思路,例如,我在專欄第 18 講曾經問過,怎麼找到最耗費 CPU 的 Java 執行緒,簡要介紹步驟:

  •   利用 top 命令獲取相應 pid,“-H”代表 thread 模式,你可以配合 grep 命令更精準定位。
top –H
  • 然後轉換成為 16 進位制。
printf "%x" your_pid
  • 最後利用 jstack 獲取的執行緒棧,對比相應的 ID 即可。

當然,還有更加通用的診斷方向,利用 vmstat 之類,檢視上下文切換的數量,比如下面就是指定時間間隔為 1,收集 10 次。

vmstat -1 -10

輸出如下:


如果每秒上下文(cs,context switch)切換很高,並且比系統中斷高很多(in,system  
interrupt),就表明很有可能是因為不合理的多執行緒排程所導致。當然還需要利用pidstat等手段,進行更加具體的定位,我就不再進一步展開了。

除了 CPU,記憶體和 IO 是重要的注意事項,比如:

  •   利用 free 之類檢視記憶體使用。
  •   或者,進一步判斷 swap 使用情況,top 命令輸出中 Virt 作為虛擬記憶體使用量,就是實體記憶體(Res)和 swap 求和,所以可以反推 swap 使用。顯然,JVM 是不希望發生大量的 swap 使用的。
  •   對於 IO 問題,既可能發生在磁碟 IO,也可能是網路 IO。例如,利用 iostat 等命令有助於判斷磁碟的健康狀況。我曾經幫助診斷過 Java 服務部署在國內的某雲廠商機器上,其原因就是 IO 表現較差,拖累了整體效能,解決辦法就是申請替換了機器。


講到這裡,如果你對系統性能非常感興趣,我建議參考Brendan Gregg提供的完整圖譜,我所介紹的只能算是九牛一毛。但我還是建議儘量結合實際需求,免得迷失在其中。


對於JVM 層面的效能分析,我們已經介紹過非常多了:

  •   利用 JMC、JConsole 等工具進行執行時監控。
  •   利用各種工具,在執行時進行堆轉儲分析,或者獲取各種角度的統計資料(如jstat -gcutil 分析 GC、記憶體分帶等)。
  •   GC 日誌等手段,診斷 Full GC、Minor GC,或者引用堆積等。


這裡並不存在放之四海而皆準的辦法,具體問題可能非常不同,還要看你是否能否充分利用這些工具,從種種跡象之中,逐步判斷出問題所在。

對於應用Profiling,簡單來說就是利用一些侵入性的手段,收集程式執行時的細節,以定位效能問題瓶頸。所謂的細節,就是例如記憶體的使用情況、最頻繁呼叫的方法是什麼,或者上下文切換的情況等。

我在前面給出的典型回答裡提到,一般不建議生產系統進行 Profiling,大多數是在效能測試階段進行。但是,當生產系統確實存在這種需求時,也不是沒有選擇。我建議使用 JFR 配合JMC來做 Profiling,因為它是從 Hotspot JVM 內部收集底層資訊,並經過了大量優化,效能開銷非常低,通常是低於 2% 的;並且如此強大的工具,也已經被 Oracle 開源出來!

所以,JFR/JMC 完全具備了生產系統 Profiling 的能力,目前也確實在真正大規模部署的雲產品上使用過相關技術,快速地定位了問題。

它的使用也非常方便,你不需要重新啟動系統或者提前增加配置。例如,你可以在執行時啟動 JFR 記錄,並將這段時間的資訊寫入檔案:

Jcmd <pid> JFR.start duration=120s filename=myrecording.jfr

然後,使用 JMC 開啟“.jfr 檔案”就可以進行分析了,方法、異常、執行緒、IO 等應有盡有,其功能非常強大。如果你想了解更多細節,可以參考相關指南。

今天我從一個典型效能問題出發,從症狀表現到具體的系統分析、JVM 分析,系統性地整理了常見效能分析的思路;並且在知識擴充套件部分,從方法論和實際操作的角度,讓你將理論和實際結合,相信一定可以對你有所幫助。

 

一課一練

關於今天我們討論的題目你做到心中有數了嗎? 今天的思考題是,Profiling 工具獲取資料的主要方式有哪些?各有什麼優缺點。