當 Lua 程式碼導致 Nginx 或 OpenResty 伺服器 CPU 佔用飆高時,最快的解決辦法是對線上工作程序進行實時剖析,找出最熱的 Lua 程式碼路徑。在本教程中,OpenResty XRay 將一個 CPU 佔用 97% 的工作程序的問題,定位到 processor.lua 第 29 行 gen_order_md5 函式中迴圈執行的 MD5 計算——全程無需修改或重啟該程序。

症狀:一個 Nginx 工作程序佔用近 100% CPU

首先執行 top 命令,檢查目標伺服器上的 CPU 使用情況。如您所見,一個 Nginx 工作程序佔用了將近 100% 的 CPU 核心資源。

top 命令輸出顯示一個 Nginx 工作程序 CPU 佔用極高,接近一個核心的 100%

使用引導式分析定位最熱的 Lua 程式碼路徑

現在讓我們來使用 OpenResty XRay 檢查這個未經修改的程序。我們可以對它進行實時分析,找出問題所在。

開啟 OpenResty XRay web 控制檯並登入,確保您正在分析正確的伺服器,然後進入引導式分析頁面。這裡可以看到您能夠分析的不同型別的問題。選擇 High CPU 問題型別。

OpenResty XRay 引導式分析頁面列出可診斷的問題型別,選擇 High CPU 用於 Lua CPU 診斷

選擇應用程式,然後選擇消耗 97% CPU 資源的程序。

在 OpenResty XRay 引導式分析中選擇消耗 97% CPU 的 Nginx 工作程序

確保應用程式的型別是正確的。通常預設值就是正確的。OpenResty XRay 可以同時分析多種語言級別。這裡我們保持 Lua 和 C 都選中的狀態。

OpenResty XRay 語言級別選擇介面,Lua 和 C 兩個級別同時啟用用於 CPU 分析

還可以設定最大分析時間,這裡保留預設值 300 秒,然後開始分析。系統會持續進行多輪分析。對於本例,第一輪分析已經足夠,我們停止分析。可以看到自動建立了一個報告。

報告顯示了佔用最多 CPU 時間的最熱 Lua 程式碼路徑。

OpenResty XRay 分析報告顯示佔用最多 CPU 時間的最熱 Lua 程式碼路徑

點選這裡檢視更多細節。

展開後的報告詳情,顯示佔用 CPU 最多的 #1 最熱 Lua 程式碼路徑的完整呼叫鏈

解讀 Lua CPU 火焰圖

報告中還有一張 Lua CPU 火焰圖,最熱的程式碼路徑用紅色標識出來。

OpenResty XRay 中的 Lua CPU 火焰圖,最熱的 Lua 程式碼路徑用紅色標出

最熱的 Lua 程式碼路徑涉及 MD5 計算函式的呼叫。

火焰圖幀顯示 MD5 計算函式呼叫佔據了大部分 Lua CPU 時間

之後的呼叫函式都來自目標應用程式的業務程式碼。

報告中 #1 最熱 Lua 程式碼路徑的呼叫鏈,gen_order_md5 之後的函式均來自業務程式碼

跳轉到精確的 Lua 原始碼行

gen_order_md5 Lua 函式開始,在應用程式業務程式碼中找到精確的原始碼行。

報告中 gen_order_md5 幀高亮,作為定位業務程式碼精確原始碼行的起點

當我們將滑鼠懸停在函式的綠色框上時,可以在出現的提示中看到 Lua 原始檔 processor.lua 的完整路徑。

滑鼠懸停在 gen_order_md5 幀上,提示框顯示 Lua 原始檔 processor.lua 的完整路徑

原始碼行號是 29。

火焰圖提示框顯示最熱 gen_order_md5 Lua 函式的原始碼行號為 29

點選圖示複製這個函式的完整 Lua 原始檔路徑。

點選複製圖示獲取 gen_order_md5 函式的完整 Lua 原始檔路徑

使用 VI 編輯器,將我們剛剛複製的程式碼路徑貼上到這裡,檢視相應的業務 Lua 程式碼。您可以使用任何您喜歡的編輯器。

在終端使用 VI 開啟復制到的 Lua 原始檔 /app/or-order-service/service/order/processor.lua

從之前的報告中,我們知道程式碼在第 29 行。

在 VI 中開啟的 processor.lua,報告指出的第 29 行被高亮

可以看到這行 Lua 原始碼確實包含了一個迴圈內的 md5 計算。

在 VI 中開啟的 Lua 原始檔 processor.lua,第 29 行顯示迴圈內的 md5 計算

它也在報告中顯示的 gen_order_md5 函式中。

本例中我們能拿到業務原始碼;如果熱點落在沒有原始碼的第三方“黑盒”模組裡,OpenResty XRay 同樣能定位到具體行——見當“黑盒”外掛吃掉 45% CPU,我們如何在無原始碼情況下定位到 Lua 第 93 行

processor.lua 中 gen_order_md5 函式定義高亮,與報告中的熱點函式一致

透過 Insights 報告自動監控 Lua CPU 佔用

OpenResty XRay 也可以自動地監控線上程序,並顯示分析報告。您可以在 Insights 頁面中找到以日和周為週期生成的報告。關於這些自動報告涵蓋哪些分析維度、如何解讀,見OpenResty XRay 的自動分析報告

OpenResty XRay Insights 頁面展示自動生成的日報和週報形式的 Lua CPU 分析報告

因此,您不是必須使用引導式分析功能。當然,引導式分析對於應用程式開發和演示是很有用的。

OpenResty XRay 是一個基於我們自己的動態追蹤技術開發的非侵入式診斷系統。它可以實時監控和掃描效能問題、行為問題和安全漏洞。

OpenResty XRay 對執行中應用進行非侵入式體檢的示意圖

如果你喜歡這個教程,請訂閱這個部落格網站和我們的 YouTube 頻道B 站頻道。謝謝!

常見問題

為甚麼我的 Nginx 工作程序 CPU 佔用接近 100%?

在本例中,Nginx 工作程序幾乎吃滿一整個 CPU 核心,原因是一條很熱的 Lua 程式碼路徑:應用業務程式碼中在迴圈裡執行的 MD5 計算。要找出您自己伺服器上是哪條 Lua 程式碼路徑在消耗 CPU,就需要對線上程序進行實時剖析。

如何找出是哪段 Lua 程式碼在消耗 CPU?

使用 OpenResty XRay 的引導式分析功能:選擇 High CPU 問題型別,選中佔用 CPU 的工作程序,並保持 Lua 和 C 兩個語言級別同時選中。生成的報告會展示最熱的 Lua 程式碼路徑、用紅色標出熱路徑的 Lua CPU 火焰圖,以及精確的原始檔和行號——在本教程中是 processor.lua 第 29 行。

分析 Lua CPU 佔用需要重啟 Nginx 嗎?

不需要。OpenResty XRay 對這個未經修改的 Nginx 程序進行了實時分析,全程沒有重啟程序,也沒有改動任何程式碼。它是基於動態追蹤技術的非侵入式診斷系統,還可以自動監控線上程序,在 Insights 頁面生成日報和週報。

關於 OpenResty XRay

OpenResty XRay 是一個動態追蹤產品,它可以自動分析執行中的應用程式,以解決效能問題、行為問題和安全漏洞,並提供可行的建議。在底層實現上,OpenResty XRay 由我們的 Y 語言驅動,可以在不同環境下支援多種不同的執行時,如 Stap+、eBPF+、GDB 和 ODB。

關於本文和關聯影片

本文和相關聯的影片都是完全由我們的 OpenResty Showman 產品從一個簡單的劇本檔案自動生成的。

關於作者

章亦春是開源 OpenResty® 專案創始人兼 OpenResty Inc. 公司 CEO 和創始人。

章亦春(Github ID: agentzh),生於中國江蘇,現定居美國灣區。他是中國早期開源技術和文化的倡導者和領軍人物,曾供職於多家國際知名的高科技企業,如 Cloudflare、雅虎、阿里巴巴, 是 “邊緣計算“、”動態追蹤 “和 “機器程式設計 “的先驅,擁有超過 22 年的程式設計及 16 年的開源經驗。作為擁有超過 4000 萬全球域名使用者的開源專案的領導者。他基於其 OpenResty® 開源專案打造的高科技企業 OpenResty Inc. 位於美國矽谷中心。其主打的兩個產品 OpenResty XRay(利用動態追蹤技術的非侵入式的故障剖析和排除工具)和 OpenResty Edge(最適合微服務和分散式流量的全能型閘道器軟體),廣受全球眾多上市及大型企業青睞。在 OpenResty 以外,章亦春為多個開源專案貢獻了累計超過百萬行程式碼,其中包括,Linux 核心、Nginx、LuaJITGDBSystemTapLLVM、Perl 等,並編寫過 60 多個開源軟體庫。

關注我們

如果您喜歡本文,歡迎關注我們 OpenResty Inc. 公司的部落格網站 。也歡迎掃碼關注我們的微信公眾號:

我們的微信公眾號

翻譯

我們提供了英文版原文和中譯版(本文)。我們也歡迎讀者提供其他語言的翻譯版本,只要是全文翻譯不帶省略,我們都將會考慮採用,非常感謝!