1. 程式人生 > >如何使用火焰圖來分析伺服器負載

如何使用火焰圖來分析伺服器負載

LucidChart 提供線上編輯流程圖、網路拓撲圖、ER 圖、 UML 圖以及腦圖等多種圖表服務,有超過 7 百萬的使用者,因其簡單直觀的互動體驗和強大的多人協作功能,是可以替代 Visio 的最佳選擇。

在 Lucid,我們使用面向服務的架構來建設我們的系統。其中字型服務(font service)就是其中之一,它負責根據字型族名稱和 unicode 編碼範圍來提供相應的字型服務,同時也對使用者上傳的字型進行校驗和檢查。在生產環境中,該服務的負載一直很高,這一點超出我們的預期(使用或等待 CPU 的平均執行緒數)。特別從去年開始,我們注意到字型服務的負載高的驚人,特別是在晚上這樣的流量低峰時期。

幸運的是最終我們找到了根本原因,並通過改進大大提高了服務的整體效能和穩定性。通過下面的內容,您將瞭解到我們是如何做到的。

圖1: 字型服務在變更前後伺服器平均負載對比

通過火焰圖來除錯和發現問題

我們從 Netflix 找到了一個非常棒的火焰圖工具,並部署到生產環境。 此工具可以將多個不同調試分析工具的資料組合在一起並生成火焰圖,以視覺化的方式展示伺服器和 JVM 的資源使用情況。

如下圖所示,每個矩形表示一個棧幀,同時矩形的寬度代表了資源(比如 CPU 時間)的使用情況,Y 軸表示呼叫棧。通過識別那些寬的矩形塊,就能快速縮小問題範圍。在除錯和排查字型服務時,它極大地幫助了我們。

圖2: 高負載時字型服務中一臺伺服器的火焰圖

在高負載狀態下,我們對字型服務收集資料並生成了幾個火焰圖。下圖是其中之一,並且特別展示了 JVM 相關棧的部分。可以分析得出,大部分時間都花在了 libz.so 這一步(gzip 使用該庫進行壓縮/解壓縮操作),剩下大部分時間都花在了 XML 轉義和 UTF-8 編碼上。

圖3: JVM 相關棧活動的區域性火焰圖

找到慢的原因

首先多囉嗦幾句這個字型服務的一些背景情況。我們將所有字型相關資料儲存在 Amazon S3 中,具體來說是將每個字型的每個 unicode 範圍分別存為一個 S3 object。當其他服務請求為了獲取字型族,一組 unicode 範圍,或者是使用者自定義字型時會向字型服務請求字型資料,接著字型服務將字型資料包裹在 XML 中返回。

功能非常簡單,並沒有什麼明顯的密集型計算。但是對於出現的高負載問題,火焰圖幫助我們識別出了問題所在—— libz,XML 轉義和 UTF-8編碼都使用了大量的 CPU。

但是為什麼會產生這麼多編碼和壓縮的消耗?記得前面提到晚上時間的負載反而是最高的嗎?我們的晚上(美國山區時間)正好是亞洲地區的白天,該地區很多使用者都使用中文、日文或韓文等亞洲語言。會進行大量的 gzip 解壓縮 → UTF-8解碼 → XML 轉義 → UTF-8編碼 → gzip 壓縮。相比於拉丁語系,單個 CJK 的 unicode 範圍比拉丁語系的 unicode 範圍大2個數量級(1MB:60KB)。所以上述的轉換過程都壓到了 CPU 上,特別壓縮和解壓縮,以及 XML 轉義這類操作。

如何改進?

字型服務對請求的響應本質上只是 S3 上原始資料的集合。它確實需要執行一些重要的附加任務,如許可權檢查和從字型族中檢索名稱。但是,字型服務根本沒必要擋在 S3 前面來代理那些字型資料!所以解決辦法很簡單, 直接用包含 S3 object 的連結(就是那些字型資料)的列表作為響應返回,字型服務不再從 S3 下載並重新編碼字型資料。所以從圖1中可以看出負載幾乎降低到可忽略的程度。

總結

通過除錯分析生產環境,我們能夠找到並消除那些不必要的任務和工作,進而降低伺服器負載。

  1. 使用例如火焰圖之類的分析工具(profiling tool)來幫助識別 CPU 高佔用的操作。
  2. 壓縮/解壓縮和各種編碼/解碼的操作都是昂貴的。
  3. 如果客戶端可以直接訪問資料,那麼相比代理(客戶端去請求)資料,直接返回連結是最好的選擇,可以顯著提高整體效能。

參考連結

[1] Brendan D. Gregg的個人網站 http://www.brendangregg.com
[2] Flame graphs http://www.brendangregg.com/flamegraphs.html
[3] 白話火焰圖 https://huoding.com/2016/08/18/531
[4] Java Flame graphs http://www.brendangregg.com/blog/2014-06-12/java-flame-graphs.html
[5] OpenRestry 關於火焰圖在 Lua 中的使用 https://moonbingbing.gitbooks.io/openresty-best-practices/flame_graph.html
[6] 在 Netflix 中的應用 http://techblog.netflix.com/2015/07/java-in-flames.html
[7] 在 Netflix 中的應用 http://techblog.netflix.com/2016/04/saving-13-million-computational-minutes.html

原文來自微信公眾號:高可用架構