Übung 3: Beheben von Leistungs- und GC-Problemen mit dotnet-dump unter Linux
Gilt für: .NET Core 2.1, .NET Core 3.1, .NET 5
In diesem Artikel wird erläutert, wie Sie das Dotnet-Dump-Tool verwenden, um .NET Core-Abbilder zu erfassen und zu analysieren und dotnet-gcdump gc-bezogene Berichte in Linux zu generieren.
Voraussetzungen
Die Mindestanforderungen für die Einhaltung dieser Problembehandlungslabore sind wie folgt:
- Eine ASP.NET Core-Anwendung, um Leistungsprobleme mit niedriger CPU- und hoher CPU-Leistung und Absturzprobleme zu veranschaulichen.
- Der lldb-Debugger, der installiert und so konfiguriert ist, dass die SOS-Erweiterung geladen wird, wenn eine Kernabbilddatei geöffnet wird.
Wenn Sie die vorherigen Teile dieser Reihe befolgt haben, sollten Sie das folgende Setup bereit haben:
- Nginx ist so konfiguriert, dass zwei Websites gehostet werden:
- Der erste lauscht auf Anforderungen mithilfe des Hostheaders "myfirstwebsite" (
http://myfirstwebsite) und Routinganforderungen an die Demo ASP.NET Core Anwendung, die auf Port 5000 lauscht. - Der zweite lauscht auf Anforderungen mithilfe des hostsamb-Hostheaders (
http://buggyamb) und Routinganforderungen an die zweite ASP.NET Core Beispielanwendung, die auf Port 5001 lauscht.
- Der erste lauscht auf Anforderungen mithilfe des Hostheaders "myfirstwebsite" (
- Beide ASP.NET Core Anwendungen sollten als Dienste ausgeführt werden, die automatisch neu gestartet werden, wenn der Server neu gestartet wird oder die Anwendung nicht mehr reagiert.
- Die lokale Linux-Firewall ist aktiviert und so konfiguriert, dass SSH- und HTTP-Datenverkehr zulässig ist.
Hinweis
Wenn Ihr Setup noch nicht bereit ist, wechseln Sie zu"Teil 2 Erstellen und Ausführen ASP.NET Core Apps".
Ziel dieser Übung
In Übung 2.2 erfassen Sie Speicherabbilddateien mithilfe von ProcDump,haben ProcDump verwendet und getestet, um kernabbilddateien manuell oder durch Überwachen der Speicherauslastung zu erfassen.
In diesem Teil erfahren Sie, wie Sie dotnet-dump verwenden, um Kernabbilddateien ohne systemeigenen Debugger zu erfassen und zu analysieren. Anschließend erfahren Sie, wie Sie dotnet-gcdump GC-bezogene Berichte generieren, die Sie auf einem Windows-basierten Computer öffnen können.
Dotnet-Dump
Dotnet-Dump ist eine weitere Möglichkeit zum Sammeln und Analysieren von Kernabbilddateien, ohne dass ein systemeigener Debugger verwendet werden muss, z. B. lldb unter Linux. Mit diesem Tool können Sie auch SOS-Befehle ausführen, um Abstürze und Gc-bezogene Probleme (Garbage Collector) zu analysieren. Dotnet-Dump ist nur in .NET Core 3.0 SDK und neueren Versionen verfügbar.
Hinweis
Dotnet-Dump ist kein systemeigener Debugger. Daher sind einige Features, z. B. das Anzeigen der nativen Stapelframes, in diesem Tool nicht verfügbar.
Wenn Sie dotnet-dump nicht installiert haben, können Sie es jetzt installieren, indem Sie den folgenden Befehl ausführen:
dotnet tool install -g dotnet-dump
Zum manuellen Erfassen von Kernabbilddateien können Sie den dotnet-dump collect Befehl verwenden. Beispiel: dotnet-dump collect -p 11724. Das Tool erfasst die gleichen zentralen Abbilddateien, die Sie mithilfe von createdump oder ProcDump gesammelt haben.
Das wichtigste Feature des Dotnet-Dumps ist, dass es verwendet werden kann, um .NET Core-Abbilddateien zu öffnen und SOS-Befehle auszuführen, die identisch mit lldb sind. Sie müssen weiterhin Symbole einrichten und die SOS-Erweiterung installieren, um eine Speicherabbilddatei mit dotnet-dump analysieren zu können.
Hinweis
Wenn Sie zuvor mit lldb gearbeitet haben, sollten Sie bereits Symbole eingerichtet und SOS installiert haben. Daher sollten Sie in der Lage sein, dieselben .NET Core-Versionsabbilddateien zu öffnen, ohne die Symbole erneut herunterladen zu müssen. Wenn Sie eine andere .NET Core-Versionsabbilddatei öffnen, für die die Symbole noch nicht heruntergeladen wurden, müssen Sie die Symbole für diese Version von .NET Core herunterladen, bevor Sie mit der Analyse beginnen.
Sammeln von Kernabbilddateien mithilfe des Dotnet-Dumps
Verwenden Sie den Befehl, um eine Kernabbilddatei mithilfe des Dotnet-Dumps zu dotnet-dump collect <PID> erfassen. Das Ermitteln der PID sollte an diesem Punkt eine einfache Aufgabe sein. Wenn Sie jedoch Hilfe benötigen, enthält dieser Befehl einen ps Parameter. Der dotnet-dump ps Befehl listet die Dotnetprozesse auf, aus denen Sie eine Speicherabbilddatei erfassen können.
Wenn Sie versuchen, den dotnet-dump ps Befehl auszuführen, treten unerwartete Ergebnisse auf.
In dieser Liste werden zwei Prozesse angezeigt. Eine davon wird jedoch als Prozess mit erhöhten Rechten angezeigt, und der Pfad kann nicht durch den dotnet-dump BEFEHL "ps" bestimmt werden. Um den Pfad zu finden, überprüfen Sie die Befehlszeileninformationen des Prozesses, indem Sie den cat /proc/<PID>/cmdline Befehl ausführen.
Hinweis
Ersetzen Sie in diesem Befehl <PID> durch die tatsächliche Prozess-ID des Zielprozesses, wie in der folgenden Beispielausgabe dargestellt. Möglicherweise erinnern Sie sich an das spezielle Verzeichnis /proc/ aus den vorherigen Abschnitten, und dass ein Prozess in Linux als ein anderer Ordner unter diesem Verzeichnis (mit dem Namen der Prozess-ID) angezeigt werden kann. Sie finden alle Details zu einem Prozess, indem Sie die <PID> / /proc/-Verzeichnisstruktur untersuchen.
Wie in diesem Screenshot gezeigt, erfahren Sie in der Ausgabe des ersten Befehls ( ) , dass es sich cat /proc/6164/cmdline um Ihre erste Demo-ASP.NET Core-Anwendung handelt. Die Ausgabe des zweiten Befehls ( cat /proc/15586/cmdline ) teilt Ihnen mit, dass dies Ihre fehlerhafte Anwendung ist.
Obwohl der dotnet-dump ps Befehl den Prozesspfad nicht abrufen konnte, sollte er dennoch in der Lage sein, die erforderlichen Abbilddateien für die Problembehandlung zu generieren. Versuchen Sie, mithilfe des Befehls eine zentrale Abbilddatei zu dotnet-dump collect erfassen. Probieren Sie zunächst die Demoanwendung aus, für die das Tool den Prozesspfad anzeigen konnte. Ausführen dotnet-dump collect -p 6164 (die Prozess-PID unterscheidet sich, wenn Sie die Übung testen).
Das Generieren der Speicherabbilddatei ist erfolgreich. Versuchen Sie nun, eine Kernabbilddatei für die fehlerhafte Anwendung zu sammeln, für die das Tool den Prozesspfad nicht auflisten konnte, wenn Sie den Befehl verwendet dotnet-dump ps haben. Führen Sie dotnet-dump collect -p 15586 dies aus, und beachten Sie, dass dies unerwartet fehlschlägt.
Die folgende Fehlermeldung wird zurückgegeben:
(13): Berechtigung verweigert /tmp/dotnet-diagnostic-15586-25444688-socket
Wenn Sie bemerkt haben, dass der dotnet-dump ps Befehl den Prozesspfad nicht abrufen konnte, haben Sie möglicherweise den Annahme, dass beim Versuch, die Kernabbilddatei zu generieren, ein Fehler auftritt.
Aus der vorherigen Fehlermeldung können Sie feststellen, dass ein Berechtigungsproblem aufgetreten ist. Aber was ist der Unterschied zwischen den beiden Prozessen, dem ersten Hosten der .NET 5-Beispielanwendung und dem zweiten Hosten der .NET Core 3-Anwendung? Vergleichen Sie die Dienstdateien für jeden Prozess. Sie sollten den Unterschied relativ einfach erkennen können: Das Benutzerkonto, das jeden Prozess ausführt, unterscheidet sich.
Die linke Seite der Liste entspricht der ersten Demoanwendung, in der alles einwandfrei funktioniert und die Anwendung als <User Name> (oder das Benutzerkonto, das Sie beim Einrichten der Umgebung und der Anmeldung verwendet haben) ausgeführt wird. Die rechte Seite entspricht der Fehlerhaften Anwendung, bei der die Speicherabbilddateisammlung fehlgeschlagen ist. und die Anwendung wird als www-Data-Benutzer ausgeführt.
Die Lösung für dieses Problem wird auf der offiziellen GitHub Seiteerläutert.
Zusammenfassung: Wenn Sie Ihren Dienstprozess als einen anderen Benutzer als den für das Konto ausführen, das Sie zum Anmelden verwendet haben, sollten Sie den dotnet-dump collect Befehl wie folgt ausführen.
Hier sehen Sie das Format des Befehls:
sudo -H -u <user name of service> bash -c "<full path to dotnet tools>/dotnet-dump collect -p <PID> -o <output path>"
Mit dem Befehl können Sie den vollständigen Pfad des Dotnet-Dump-Tools whereis dotnet-dump ermitteln.
Der Ausgabepfad sollte ein Verzeichnis sein, in dem der Benutzer über die Schreibberechtigung verfügt. In der Regel können Sie das Verzeichnis unter dem Verzeichnis /tmp erstellen und die Speicherabbilddatei später in Ihr Startverzeichnis kopieren.
Öffnen und Analysieren von Kernabbilddateien mithilfe von Dotnet-Dump
Für diese Übung müssen Sie keine neue Speicherabbilddatei erfassen. Stattdessen können Sie eine der vorherigen Abbilddateien öffnen, die Sie mithilfe von createdump erfasst haben. Wenn Sie möchten, können Sie eine zentrale Speicherabbilddatei öffnen, die Sie mithilfe des Dotnet-Dumps erfasst haben.
Um die Speicherabbilddatei mithilfe des Dotnet-Dumps zu öffnen, führen Sie sie aus dotnet-dump analyze ~/dumps/coredump.manual.2.11724 (der Name der Speicherabbilddatei ist auf Ihrem Computer unterschiedlich). Dies ist dasselbe verwaltete Debuggermodul, das Sie zuvor in lldb verwendet haben. Wenn Ihre Symbole ordnungsgemäß konfiguriert sind und SOS ordnungsgemäß installiert ist, können Sie alle SOS-Befehle ausführen, wie sie mithilfe von lldb möglich sind. In der folgenden Liste sehen Sie den clrstack Befehl in Aktion.
Es gibt zwei Dinge, die Sie beachten sollten:
- Da es sich hierbei nicht um einen systemeigenen Debugger handelt, können Sie keine systemeigenen Lldb-Debuggerbefehle ausführen, z. B. den Speicherlesebefehl, den Sie zuvor in lldb verwenden mussten. Sie können nur SOS-Befehle ausführen.
- Die automatische Vervollständigung funktioniert nicht. In lldb können Sie mit der Eingabe eines Befehls beginnen und dann die TAB-Taste drücken, um den Befehl automatisch auszuführen, wie sie dies in der Befehlszeile und shell getan haben. Das Feature funktioniert nicht für dotnet-dump. Dies sollte sich jedoch nicht auf Ihre Schulung auswirken.
Während Sie die Kernabbilddatei geöffnet haben, nutzen Sie diese Gelegenheit, um einige neue SOS-Befehle zu üben.
Wie können Sie die CPU-Auslastung in einem Speicherabbild überprüfen? Der threadpool Befehl kann hilfreich sein, um diese Informationen anzuzeigen. Es meldet die "gesamte CPU-Auslastung des Servers" (nicht nur für den Prozess, der gedebuggt wird), aber es bietet immer noch eine allgemeine Vorstellung des Ressourcenverbrauchs auf dem Computer zum Zeitpunkt der Generierung der Speicherabbilddatei. Der folgende Screenshot zeigt, dass die gesamte CPU-Auslastung des Servers etwa 94 % betrug.
Hinweis
Der Server, der zum Erstellen dieser Listen verwendet wurde, war mit zwei CPUs ausgestattet. Aus diesem Grund werden Berichte wie diese generiert.
Die gleiche Ausgabe zeigt auch die Threadpoolkonfiguration und in der vorherigen Liste, dass sieben Arbeitsthreads verfügbar waren und sechs davon ausgeführt wurden. Diese Informationen sind hilfreich, wenn Sie Probleme mit der Konfiguration von Threadpools beheben.
Möchten Sie den Aufrufstapel aller ausgeführten Threads gruppieren und eine zusammengeführte Anzeige anzeigen, ähnlich dem Visual Studio Parallel Stacks-Bereich? Ausführen, pstacks um ein ähnliches Ergebnis zu erhalten.
Um Die verfügbaren SOS-Befehle besser zu verstehen, öffnen Sie die SOS-Hilfe, und überprüfen Sie jeden Befehl einzeln, um sich mit der Leistungsfähigkeit des SOS-Debuggens vertraut zu machen.
Dotnet-Dump ist nützlich, wenn die Installation von lldb keine Option für Sie ist. Die Schulung wird fortgesetzt, indem ein anderer Ansatz zur Analyse von GC-Heaps eingeführt wird.
Dotnet-gcdump
Dotnet-gcdump ist ein weiteres nützliches Tool. Sie ist in .NET Core 3.1 oder höher verfügbar.
Die Idee hinter diesem Tool ist, dass Sie kein vollständiges Prozessabbild benötigen, um eine Untersuchung in vielen Szenarien durchführen zu können, in denen Sie hauptsächlich den verwalteten Heap betrachten möchten. Warum also nicht nur die Heap-Informationen erfassen und einen Bericht darüber generieren? Am wichtigsten ist, dass die von diesem Tool generierten GC-Abbilddateien portierbar sind und auf einem Windows Computer analysiert werden können. Da dieser Typ von Speicherabbilddatei nur die GC-Heap-Informationen enthält, können Sie sie nicht in lldb öffnen, um die Threads oder die Threadaufrufstapel zu untersuchen. Sie können es jedoch in PerfView oder in Visual Studio öffnen.
Dies mag unerhört klingen, aber... Eines müssen Sie beachten: Dotnet-gcdump Löst eine Gen 2 GC-Sammlung in Ihrem Prozess aus, um die benötigten Daten zu sammeln. Verwenden Sie dieses Tool in der Produktion sorgfältig. Verwenden Sie sie nur, wenn Sie wissen, dass Sie dies auf jeden Fall tun müssen.
Wann müssen Sie dieses Tool möglicherweise verwenden? Wenn sich Ihr Prozess bereits in einem nicht reagierenden Zustand (Hung) befindet und es nichts gibt, um sich von der Situation zu wiederherstellen, und Sie beabsichtigen, die Anwendung neu zu starten. Anschließend können Sie vor dem Neustart einen Gcdump erfassen, damit Sie zu einem späteren Zeitpunkt mindestens einen Satz von Informationen analysieren können.
Die von diesem Tool erfassten Informationen sind für die folgenden Aufgaben hilfreich:
- Vergleichen Sie die Anzahl der Objekte nach Typ im Heap.
- Analysieren Sie die Objektwurzeln.
- Bestimmen Sie, welche Objekte einen Verweis auf welche Typen haben.
- Andere statistische Analysen zu Objekten auf dem Heap.
Wenn Sie dieses Tool noch nicht installiert haben, tun Sie dies jetzt. Sie müssen nur den folgenden Befehl ausführen:
dotnet tool install --global dotnet-gcdump
Gcdump mit dotnet-gcdump-Befehl sammeln
Die gleiche Regel gilt für dotnet-gcdump das Dotnet-Dumptool: Wenn Sie den Prozess für einen anderen Benutzer ausführen, müssen Sie den Befehl im folgenden Format ausführen:
sudo -H -u <user name of service> bash -c "<full path to dotnet tools>/dotnet-gcdump collect -p <PID> -o <output path>"
Weitere Informationen finden Sie im Abschnitt zum Sammeln von Kernabbilddateien mithilfe des Abschnitts "dotnet-dump", wenn ihnen dieser Befehl nicht vertraut ist.
Sie sollten nun über alles verfügen, was Sie zum Sammeln von Prozessinformationen mithilfe des Tools benötigen. Das Ziel besteht darin, zwei Sätze von Daten zu sammeln, so wie Sie dies mithilfe der Zentralen Speicherabbilddateien getan haben. Der Zielprozess wird erneut für einen anderen Benutzer ausgeführt. Daher müssen Sie das "Bash"-Format für den Startbefehl verwenden.
Die Schritte sind hier aufgeführt:
Reproduzieren Sie das Leistungsproblem, indem Sie sechs Anforderungen an die Slow-Seite ausführen, indem Sie das Aufladegenerator-Tool verwenden, das in der ASP.NET Core Website enthalten ist.
Erfassen Sie den ersten Gcdump, indem Sie den folgenden Befehl ausführen:
sudo -H -u www-data bash -c "/home/<User Name>/.dotnet/tools/dotnet-gcdump collect -p 15586 -o /tmp/gcreport1.gcdump"Hinweis: Ersetzen Sie in diesem Befehl die PID durch Ihre eigene.
Warten Sie 5 bis 10 Sekunden, und erfassen Sie dann den zweiten gcdumpby, der den folgenden Befehl ausführt:
sudo -H -u www-data bash -c "/home/<User Name>/.dotnet/tools/dotnet-gcdump collect -p 15586 -o /tmp/gcreport2.gcdumpHinweis: Ersetzen Sie in diesem Befehl Ihre PID durch die ursprüngliche PID.
Denken Sie daran, dass Sie ein Leistungsproblem beheben. Es empfiehlt sich, mehrere Datensätze zu verwenden, damit Sie vergleichen können, wie sich der verwaltete Heap im Laufe der Zeit weiterentwickelt hat. Das Ergebnis dieser Befehle ist, dass zwei GCDUMP-Dateien generiert werden.
Erstellen von Berichten aus gcdump-Dateien
Kopieren Sie die gcdump-Dateien auf Ihren Windows-basierten Computer, und öffnen Sie sie in Visual Studio 2019. Der folgende Screenshot zeigt die Vergleichsergebnisse beider gcdump-Dateien, die für diese Liste erstellt wurden. Wie Sie sehen können, gibt es einen großen Unterschied zwischen den Werten des String-Objekttyps. Sie können auch einige Stamminformationen zu Objekten abrufen.
Dies kann hilfreiche Informationen sein.
Alternativ können Sie gcdump-Berichte in PerfViewöffnen.
Wenn Sie nur den verwalteten Heap betrachten müssen, könnte dies die schnellste Option für Sie sein. Denken Sie daran, bei der Verwendung in der Produktion Vorsicht walten zu dotnet-gcdump lassen, da dies, wie bereits erwähnt, einen vollständigen GC in Ihrem Prozess auslöst und dies zu langen Pausen führen kann. Verwenden Sie dieses Tool in der Produktion sorgfältig und nur bei Bedarf, wenn Sie ein Speicherproblem beheben.