在 Azure App 服務 平臺上擷取記憶體轉儲
本文提供擷取記憶體轉儲Microsoft Azure App 服務 偵錯功能的指引。 您使用的擷取方法是由您擷取記憶體轉儲以針對效能或可用性問題進行疑難解答的案例所決定。 例如,擷取記憶體轉儲與擲回例外狀況或回應速度緩慢的進程不同,因為發生過多的記憶體耗用量。 此內容中的進程是 網際網路資訊服務 (IIS) 背景工作進程 (W3WP,以w3wp.exe方式執行)。
將記憶體轉儲案例對應至 Azure App 服務 偵錯功能
下表提供每個 App Service 功能執行以產生記憶體轉儲之命令的相關建議。 擷取記憶體轉儲的方法很多,程式可能會造成混淆。 如果您已經熟悉擷取 W3WP 記憶體轉儲,這項資訊並不適合變更您的方法。 相反地,我們希望為尚未開發喜好設定的無經驗使用者提供指引。
案例 | Azure App 服務 偵錯功能 | Command |
---|---|---|
無回應或緩慢 | 自動癒合(要求持續時間) | procdump -accepteula -r -dc "Message" -ma <PID> <PATH> |
當機 (行程終止) | 當機監視 | 使用 DbgHost 擷取記憶體轉儲 |
當機 (已處理的例外狀況) | Application Insights/Log Analytics 中的追蹤 | 無 |
當機 (未處理的例外狀況) | Application Insights 快照集偵錯工具 | 無 |
過多的CPU使用量 | 主動式CPU監視 | procdump -accepteula -dc "Message" -ma <PID> <PATH> |
過度耗用記憶體 | 自動癒合(記憶體限制) | procdump -accepteula -r -dc "Message" -ma <PID> <PATH> |
注意
我們在沒有回應或緩慢的案例中擷取 W3WP 進程記憶體傾印的次要建議。 如果該案例可重現,而且您想要立即擷取傾印,您可以使用 收集記憶體轉儲 診斷工具。 此工具位於 Azure 入口網站 中指定 App Service Web 應用程式的診斷和解決問題工具組頁面。 另一個檢查一般例外狀況和效能不佳的位置是在 [應用程式事件 記錄檔] 頁面上。 (您也可以從 存取應用程式記錄診斷並解決問題頁面。我們會討論「展開 Azure App 服務 偵錯功能描述」一節中的所有可用方法。
展開的程式案例描述
本節包含上表所顯示六個案例的詳細描述。
沒有回應或緩慢的案例
對網頁伺服器提出要求時,通常必須執行某些程序代碼。 程式代碼執行會在線程上的 w3wp.exe 進程內發生。 每個線程都有一個堆疊,顯示目前正在執行的內容。
沒有回應的案例可以是永久的(而且可能會逾時)或緩慢。 因此,沒有回應的案例是要求執行所花費的時間超過預期的情況。 您可能認為速度很慢,取決於程序代碼正在做什麼。 對有些人來說,三秒的延遲速度很慢。 對其他人而言,可以接受 15 秒的延遲。 基本上,如果您看到指出速度緩慢的效能計量,或超級使用者指出伺服器回應速度比正常慢,則您有沒有回應或緩慢的案例。
當機 (行程終止) 案例
多年來,Microsoft .NET Framework 已改善例外狀況的處理。 在目前的 .NET 版本中,例外狀況處理體驗會更好。
在過去,如果開發人員未在 try-catch 區塊內放置代碼段,而且擲回例外狀況,進程就會終止。 在此情況下,開發人員程式代碼中未處理的例外狀況終止了程式。 較新式版本的 .NET 會處理其中一些「未處理的」例外狀況,讓執行程式代碼的進程不會當機。 不過,並非所有未處理的例外狀況都會直接從自定義程式代碼擲回。 例如,存取違規(例如0xC0000005和0x80070005)或堆棧溢位可能會終止進程。
當機 (已處理的例外狀況) 案例
雖然軟體開發人員特別小心,以判斷程式代碼執行的所有可能案例,但可能發生非預期的情況。 下列錯誤可能會觸發例外狀況:
- 非預期的 Null 值
- 無效的轉換
- 遺漏的具現化物件
最佳做法是將程式代碼執行放入 try-catch 程式代碼區塊中。 如果開發人員使用這些區塊,程式代碼就有機會透過特別管理非預期事件之後的內容,順利失敗。 已處理的例外狀況是在 try 區塊內擲回的例外狀況,並攔截在對應的 catch 區塊中。 在此情況下,開發人員預期會發生例外狀況,並在程式代碼區段周圍撰寫適當的 try-catch 區塊。
在 catch 區塊中,將足夠的資訊擷取到記錄來源會很有用,以便重現問題,並最終解決。 例外狀況是效能方面的昂貴程式代碼路徑。 因此,有許多例外狀況會影響效能。
當機 (未處理的例外狀況) 案例
當程式代碼嘗試採取不預期會發生的動作時,就會發生未處理的例外狀況。 如同在「當機」(進程終止)案例中,該程式代碼並未包含在 try-catch 程式代碼區塊內。 在此情況下,開發人員並不預期程式代碼的該區段可能發生例外狀況。
此案例與前兩個例外狀況案例不同。 在 「當機」(未處理的例外狀況) 案例中,有問題的程式代碼是開發人員撰寫的程序代碼。 它不是擲回例外狀況的架構程序代碼,也不是造成w3wp.exe進程終止的未處理例外狀況之一。 此外,因為擲回例外狀況的程式代碼不在 try-catch 區塊內,因此沒有機會正常處理例外狀況。 對程式代碼進行疑難解答一開始會比較複雜。 您的目標是尋找例外狀況文字、類型和堆疊,以識別擲回這個未處理的例外狀況的方法。 該資訊可讓您識別您必須新增 try-catch 程式代碼區塊的位置。 然後,開發人員可以新增類似的邏輯,以記錄應該存在於當機(未處理的例外狀況)案例中的例外狀況詳細數據。
過多的CPU使用量案例
CPU 使用量過多? 這種情況取決於程序代碼的用途。 一般而言,如果來自w3wp.exe程式的CPU使用量為80%,則您的應用程式處於可能導致各種徵兆的危急情況。 一些可能的徵兆如下:
- 速度緩慢
- 錯誤
- 其他未定義的行為
如果網站只是傳遞靜態 HTML 檔案,即使是 20% 的 CPU 使用量也可以視為過度使用。 透過產生記憶體轉儲來對過度 CPU 尖峰的驗屍疑難解答,可能無法協助您判斷正在使用它的特定方法。 最好的做法是判斷哪些要求可能需要最長的時間,然後藉由測試已識別的方法嘗試重現問題。 該程式假設您不會在擷取該高載的效能系統上執行效能監視器。 在許多情況下,您可以讓監視器持續即時執行,以造成效能問題。
過多的記憶體耗用量案例
如果應用程式是在32位進程中執行,記憶體耗用量過多可能是個問題。 即使是少量的活動也會耗用 2-3 GB 的已配置虛擬地址空間。 不論可用的物理記憶體數量為何,32 位進程都不能超過總計 4 GB。
64 位進程會配置比 32 位進程更多的記憶體。 64 位進程可能會耗用伺服器上的物理記憶體數量,而進程會取用其配置的虛擬位址空間。
因此,構成過多記憶體耗用量問題的因素取決於下列因素:
- 行程位 (32 位或 64 位)
- 被視為「正常」的記憶體使用量。
如果您的進程耗用記憶體超過預期,請收集記憶體轉儲進行分析,以判斷耗用記憶體資源的內容。 如需詳細資訊,請參閱 在 App Service 耗用太多記憶體時建立 App Service 的記憶體轉儲。
現在,您對於記憶體轉儲可協助您進行疑難解答的不同進程案例有更多內容,我們將討論在 Azure App 服務 平臺上擷取記憶體轉儲的建議工具。
展開 Azure App 服務 偵錯功能描述
在「將記憶體傾印案例對應至 Azure App 服務 偵錯功能」一節的數據表中,我們識別出六個偵錯功能,其目標是收集記憶體轉儲。 當您選取 [診斷工具] 圖格時,您可以從 [診斷和解決問題] 頁面上的 [Azure 入口網站 存取這些功能。
在下列各節中,我們會更詳細地討論這些偵錯功能。
自動癒合 (要求持續時間) 功能
如果 響應花費的時間超過預期完成,自動癒合 (要求持續時間)功能對於擷取記憶體轉儲很有用。 您可以在上一個螢幕快照的 [診斷工具] 圖格中看到自動癒合的連結。 選取該連結以直接移至功能,或選取 [診斷工具] 圖格以檢閱 [診斷工具] 頁面上的所有可用工具。 如需如何設定這項功能的詳細資訊,請參閱下列文章:
自動癒合功能會顯示在下列螢幕快照中。
當問題目前發生或重現時,另一個名為「收集記憶體傾印」的功能在此案例中很有用。 此功能會根據手動需求快速收集記憶體轉儲。
收集記憶體轉儲功能
若要瞭解收集記憶體轉儲功能的設定,請參閱 收集記憶體轉儲應用程式服務。 此方法需要手動介入。 下列螢幕快照顯示 [ 收集記憶體傾印 ] 頁面。
若要使用此功能,請選取要在其中儲存記憶體轉儲的記憶體帳戶。 然後,選取您要從中收集記憶體轉儲的伺服器實例。 如果您有多個實例,請確定您正在偵錯的問題發生在該實例上。 請注意,在作業中的生產應用程式上,重新啟動可能不是最佳狀態。
當機監視功能
如果未處理的例外狀況導致 W3WP 進程終止,當機監視功能可用於擷取記憶體轉儲。 下列螢幕快照顯示診斷工具中的 [當機監視] 頁面:
若要檢視有關如何在 Azure App 服務 中設定當機監視功能的引導式逐步解說,請參閱 Azure App 服務 中的當機監視。
Application Insights/Log Analytics 功能的追蹤
已處理的例外狀況是一種案例,其中 try-catch 區塊中包含的程式代碼會嘗試採取非預期或不支援的動作。 例如,下列代碼段會嘗試將數位除以零,即使這是非法作業:
decimal percentage = 0, number = 1000, total = 0;
try
{
percentage = number / total;
}
catch (DivideByZeroException divEx)
{
_logger.LogError("A handled exception just happened: -> {divEx.Message}", divEx.Message);
}
此代碼段會導致處理零除例外狀況,因為不支援的數學運算會放在 try-catch 區塊內。 除非您刻意 在應用程式程式代碼中包含 Microsoft.ApplicationInsights NuGet 套件,然後新增程式代碼來記錄資訊,否則 Application Insights 不會記錄已處理的例外狀況。 如果您在新增程式代碼之後發生例外狀況,您可以在Log Analytics中檢視專案,如下列螢幕快照所示。
下列 Kusto 程式代碼包含用來從 Log Analytics 擷取數據的查詢:
traces
| where message has "handled"
| project timestamp, severityLevel, message, operation_Name, cloud_RoleInstance
數據 message
行是您可以儲存尋找例外狀況根本原因所需詳細數據的位置。 用來撰寫此查詢的程式代碼位於零除代碼段中。 撰寫此程式代碼的軟體開發人員是詢問這類例外狀況和分析根本原因所需的屬性的最佳人手。
將這項功能新增至應用程式程式代碼的最佳方法取決於您擁有的應用程式程式代碼堆疊和版本(例如,ASP.NET、ASP.NET Core、MVC、Razor 等等)。 若要判斷案例的最佳方法,請檢閱 使用 .NET 的 Application Insights 記錄。
應用程式事件記錄檔 (已處理的例外狀況) 功能
您也可以在 Azure 入口網站 診斷工具的 [應用程式事件記錄檔] 頁面的 [已處理例外狀況] 中找到未處理的例外狀況,如下列螢幕快照所示。
在此情況下,您會收到您透過程式代碼記錄的相同錯誤訊息。 不過,您會在如何自定義 Application Insights 追蹤記錄上的查詢方面失去一些彈性。
Application Insights 快照調試程式功能
未處理的例外狀況也會記錄在 [應用程式事件 記錄檔] 頁面上,如下一節的輸出文字所示。 不過,您也可以 啟用 Application Insights 快照集調試程式。 此方法不需要您將任何程式代碼新增至應用程式。
應用程式事件記錄檔 (未處理的例外狀況) 功能
下列輸出來自 Azure 入口網站 中診斷工具的 [應用程式事件記錄] 頁面。 它會顯示未處理應用程式例外狀況的一些範例文字:
Category: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware
EventId: 1
SpanId: 311d8cb5d10b1a6e
TraceId: 041929768411c12f1c3f1ccbc91f6751
ParentId: 0000000000000000
RequestId: 8000006d-0001-bf00-b63f-84710c7967bb
RequestPath: /Unhandled
An unhandled exception has occurred while executing the request.
Exception:
System.DivideByZeroException: Attempted to divide by zero.
at System.Decimal.DecCalc.VarDecDiv(DecCalc& d1, DecCalc& d2)
at System.Decimal.op_Division(Decimal d1, Decimal d2)
at contosotest.Pages.Pages Unhandled.ExecuteAsync()
in C:\Users\contoso\source\repos\contosorepo\contosorepo\Pages\Unhandled.cshtml:line 12
應用程式記錄中處理例外狀況的其中一個差異在於堆疊的存在,可識別擲回例外狀況的方法和行。 此外,您可以放心地 假設 Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware 功能包含程式代碼來攔截此未處理的例外狀況,以避免終止程式。 例外狀況會顯示在 [失敗] 頁面的 [例外狀況] 索引卷標上的 Application Insights 中,如下列螢幕快照所示。
在此檢視中,您會看到所有 例外狀況,而不只是您要搜尋的例外狀況。 應用程式中發生之所有例外狀況的圖形表示法有助於取得系統健康情況的概觀。 相較於 Application 事件記錄檔,Application Insights 儀錶板在視覺上更實用。
主動式CPU監視功能
在過多的CPU使用量案例中,您可以使用主動式CPU監視工具。 如需此工具的相關信息,請參閱 在 CPU 問題發生之前減輕您的 CPU 問題。 下圖顯示診斷工具中的 [主動式 CPU 監視] 頁面。
您應該將 80% 以上的 CPU 使用量視為需要立即調查的嚴重情況。 在 [ 主動式 CPU 監視 ] 頁面中,您可以設定您想要根據下列數據監視類別擷取記憶體轉儲的案例:
- CPU 閾值
- 閾值秒
- 監視頻率
CPU 閾值 會識別目標進程所使用的計算機 CPU 數目(在此案例中為 W3WP)。 臨界值秒是CPU閾值使用CPU的時間量。 例如,如果總共 30 秒有 75% 的 CPU 使用量,則會擷取記憶體轉儲。 如在 [ 主動式 CPU 監視 ] 頁面上設定,系統會每隔 15 秒檢查一次進程是否有閾值缺口。
自動癒合 (記憶體限制) 功能
如果進程耗用超過預期的記憶體,自動癒合(記憶體限制)功能對於擷取記憶體轉儲很有用。 同樣地,注意位 (32 或 64)。 如果您在32位進程內容中遇到記憶體壓力,而且預期記憶體耗用量,您可能會考慮將位變更為64。 一般而言,如果您變更位,您也必須重新編譯應用程式。
變更位不會減少使用的記憶體數量。 它確實允許進程使用超過 4 GB 的總記憶體。 不過,如果記憶體耗用量不如預期,您可以使用此功能來判斷耗用記憶體的內容。 然後,您可以採取動作來控制記憶體耗用量。
在 [展開 Azure App 服務 偵錯功能描述] 區段中,您可以在第一個螢幕快照的 [診斷工具] 圖格中看到自動癒合的連結。 選取該連結以直接移至功能,或選取圖格並檢閱 [診斷工具] 頁面中的所有可用工具。 如需詳細資訊,請移至 Azure App 服務 診斷概觀的一節。
自動癒合功能會顯示在下列螢幕快照中。
當您選取 [ 記憶體限制 ] 圖格時,您可以選擇輸入記憶體值,以在記憶體限制遭到入侵時觸發記憶體轉儲的擷取。 例如,如果您輸入 6291456 作為值,則會在取用 6 GB 記憶體時,取用 W3WP 進程的記憶體轉儲。
如果問題目前發生或可重現,則收集記憶體轉儲功能在此案例中很有用。 此功能會根據手動需求快速收集記憶體轉儲。 如需詳細資訊,請參閱一節。
展開的命令描述
記憶傾印收藏的藝術需要一些時間才能學習、體驗和完美。 如您所瞭解,不同的程式是以程式所顯示的徵兆為基礎,如一節中的表格所列。 相反地,下表比較 Azure App 服務 的記憶體傾印擷取命令與您從 Kudu 控制台手動執行的 procdump 命令。
案例 | Azure App 服務 命令 | 一般 procdump 命令 |
---|---|---|
無回應或緩慢 | procdump -accepteula -r -dc "Message" -ma <PID> <PATH> |
procdump -accepteula -ma -n 3 -s # <PID> |
當機 (行程終止) | 使用 DbgHost 擷取記憶體轉儲 | procdump -accepteula -ma -t <PID> |
當機 (已處理的例外狀況) | 無 (Application Insights) | procdump -accepteula -ma -e 1 -f <filter> <PID> |
當機 (未處理的例外狀況) | 無 (Application Insights 快照調試程式) | procdump -accepteula -ma -e <PID> |
過多的CPU使用量 | procdump -accepteula -dc "Message" -ma <PID> <PATH> |
procdump -accepteula -ma -n 3 -s # -c 80 <PID> |
過度耗用記憶體 | procdump -accepteula -r -dc "Message" -ma <PID> <PATH> |
procdump -accepteula -ma -m 2000 <PID> |
您在記憶體傾印擷取功能中使用的命令 Azure App 服務 與手動擷取傾印時所使用的 procdump 命令不同。 如果您檢閱上一節,您應該注意到 Azure App 服務 中的記憶體傾印收集入口網站功能會公開設定。 例如,在數據表中過多的記憶體耗用量案例中,平臺執行的命令不包含記憶體閾值。 不過,一般 procdump 命令數據行中顯示的命令會指定記憶體閾值。
名為 DaaS(診斷即服務)的工具負責管理和監視 Azure App 服務 偵錯入口網站中指定的組態。 此工具會在執行 Web 應用程式的虛擬機 (VM) 上,以 Web 作業的形式執行。 此工具的優點是您可以以 Web 伺服器陣列中的特定 VM 為目標。 如果您嘗試直接使用 procdump 來擷取記憶體轉儲,在特定的實例上識別、目標、存取和執行該命令可能會很困難。 如需 DaaS 的詳細資訊,請參閱 DaaS – Azure 網站的診斷即服務。
過多的CPU使用量 是平臺管理記憶體傾印收集,使其符合建議的 procdump 模式的另一個原因。 如上表所示,procdump 命令會收集三個 (-n 3
) 記憶體傾印 (-ma
) 相隔 30 秒 (-s #
,也就是 #
30), 當 CPU 使用量大於或等於 80% (-c 80
)。 最後,您會將進程識別碼 (<PID>
) 提供給 命令: procdump -accepteula -ma -n 3 -s # -c 80 <PID>
。
您可以在「主動式 CPU 監視」一節中看到入口網站設定。 為了簡潔起見,該區段只顯示前三個組態選項: CPU 閾值 (-c
)、 閾值秒 (-s
),以及 監視頻率。 下列螢幕快照說明[ 設定動作]、 [最大動作 ]-n
和 [最大持續時間 ] 是額外的可用功能。
在您研究擷取記憶體傾印的不同方法之後,下一個步驟是練習進行擷取。 您可以使用 GitHub 上的程式碼範例搭配 IIS 偵錯實驗室 和 Azure Functions 來模擬兩個數據表中列出的每個案例。 將程式代碼部署至 Azure App 服務 平台之後,您可以使用這些工具來擷取每個指定案例下的記憶體轉儲。 經過一段時間和之後的練習,您可以使用 Azure App 服務 偵錯功能來完善擷取記憶體轉儲的方法。 下列清單包含一些建議,讓您繼續了解記憶體轉儲收集:
擷取記憶體轉儲會耗用大量的系統資源,並進一步中斷效能。
在第一次機會上擷取記憶體傾印並非最佳,因為您可能會擷取太多。 這些第一次發生記憶體傾印最有可能無關緊要。
建議您先停用 Application Insights,再擷取 W3WP 記憶體轉儲。
收集記憶體轉儲之後,下一個步驟是分析記憶體轉儲來判斷問題的原因,然後更正該問題。
後續步驟 (分析記憶體轉儲)
討論如何分析記憶體轉儲超出本文的範圍。 不過,該主題有許多資源,例如 Defrag Tools 訓練系列和 必須知道的 WinDbg 命令清單。
您可能已經注意到 上一個螢幕快照中的 [設定動作] 選項。 此選項的預設設定為 CollectAndKill。 此設定表示收集記憶體轉儲之後,進程會終止。 名為 CollectKillAndAnalyze 的設定會分析所收集的記憶體轉儲。 在該案例中,平臺分析可能會發現問題,因此您不需要在 WinDbg 中開啟記憶體轉儲並加以分析。
在 Azure App 服務 平臺上,還有其他選項可用來疑難解答和診斷效能問題。 本文著重於記憶體傾印收集,並提供一些建議,以使用這些方法來接近診斷。 如果您已經學習、體驗和完善您的收集程式,而且它們適合您,您應該繼續使用這些程式。
與我們連絡,以取得說明
如果您有問題或需要相關協助,請建立支援要求,或詢問 Azure community 支援。 您也可以向 Azure 意見反應社群提交產品意見反應。