Verschiedene Debugging-Methoden in OpenResty
API7.ai
December 16, 2022
In der Kommunikationsgruppe von OpenResty stellen Entwickler oft diese Frage: Wie debuggt man in OpenResty? Soweit ich weiß, gibt es einige Tools in OpenResty, die Breakpoint-Debugging unterstützen, einschließlich eines Plugins in VSCode, aber sie werden bisher nicht weit verbreitet verwendet. Sogar der Autor agentzh und einige Mitwirkende, die ich kenne, verwenden die einfachsten Methoden wie ngx.log
und ngx.say
zum Debuggen.
Das ist für die meisten Neulinge nicht freundlich. Bedeutet das, dass die vielen Kern-Maintainer von OpenResty nur die primitive Methode des Log-Drucks verwenden, wenn sie auf ein schwieriges Problem stoßen?
Natürlich nicht. In der Welt von OpenResty sind SystemTap
und Flame Graphs die Standardtools, um schwierige Probleme und Leistungsprobleme zu behandeln. Wenn Sie eine Frage dazu in einer Mailingliste oder einem Issue stellen, wird der Projekt-Maintainer Sie bitten, ein Flame Graph hochzuladen und eine grafische statt einer textuellen Beschreibung zu verlangen.
In den nächsten beiden Artikeln werde ich mit Ihnen über das Debuggen und das speziell für das Debuggen entwickelte Toolset von OpenResty sprechen. Heute beginnen wir damit, uns anzusehen, was für das Debuggen von Programmen verfügbar ist.
Breakpoints und Log-Druck
Während eines großen Teils meiner Arbeit habe ich mich auf die fortgeschrittenen Debugging-Funktionen der IDE (integrierte Entwicklungsumgebung) verlassen, um Programme zu verfolgen, was natürlich schien. Für Probleme, die in einer Testumgebung reproduziert werden können, egal wie komplex, bin ich zuversichtlich, dass ich die Ursache des Problems finden kann. Der Grund ist, dass der Bug wiederholt reproduziert werden kann, und die Ursache kann durch das Setzen von Breakpoints und das Drucken von Logs gefunden werden. Alles, was man braucht, ist Geduld.
Aus dieser Sicht ist das Lösen von stabil wiederkehrenden Bugs in einer Testumgebung eine körperliche Arbeit. Die meisten Bugs, die ich in meiner Arbeit löse, fallen in diese Kategorie.
Es gibt jedoch zwei Voraussetzungen: eine Testumgebung und stabile Reproduzierbarkeit. Die Realität ist jedoch oft weniger ideal. Wenn der Bug nur in der Produktionsumgebung reproduziert wird, gibt es dann eine Möglichkeit, ihn zu debuggen?
Hier empfehle ich ein Tool – Mozilla RR
. Sie können es als einen Rekorder betrachten, der das Verhalten des Programms aufzeichnet und dann wiederholt abspielt. Ehrlich gesagt, egal ob in der Produktions- oder Testumgebung, solange Sie den "Beweis" des Bugs aufzeichnen können, kann er als "Beweis vor Gericht" verwendet werden, um ihn langsam zu analysieren.
Binärer Suchalgorithmus und Kommentare
Bei einigen großen Projekten kann der Bug jedoch von einem der vielen Dienste stammen, oder es könnte ein Problem mit der SQL-Abfrage der Datenbank geben. In diesem Fall, selbst wenn der Bug stabil reproduziert werden kann, können Sie nicht sicher sein, in welchem Teil der Bug aufgetreten ist. Daher versagen Aufzeichnungstools wie Mozilla RR
.
An diesem Punkt könnten Sie sich an den klassischen "binären Suchalgorithmus" erinnern. Wir kommentieren zunächst die Hälfte der Logik im Code aus, und wenn das Problem weiterhin besteht, liegt der Bug im nicht auskommentierten Code. Also kommentieren wir die verbleibende Hälfte der Logik aus und setzen die Schleife fort. Innerhalb weniger Durchläufe wird das Problem auf eine völlig handhabbare Größe eingegrenzt.
Dieser Ansatz mag etwas dumm klingen, ist aber in vielen Szenarien effizient. Natürlich, mit dem technologischen Fortschritt und der zunehmenden Komplexität der Systeme, empfehlen wir die Verwendung eines Standards wie OpenTracing
für verteilte Ablaufverfolgung.
OpenTracing kann in verschiedenen Teilen des Systems eingebettet werden und die aus mehreren Span
s bestehende Aufrufkette und Ereignisverfolgung über Trace ID
an den Server melden, um sie zu analysieren und grafisch darzustellen. Dies kann Entwicklern helfen, viele versteckte Probleme zu finden, und die historischen Daten werden gespeichert, sodass wir sie jederzeit vergleichen und anzeigen können.
Wenn Ihr System komplexer ist, wie in einer Microservices-Umgebung, dann sind Zipkin
, Apache SkyWalking
gute Wahlmöglichkeiten.
Dynamisches Debugging
Die oben beschriebenen Debugging-Methoden reichen aus, um die meisten Probleme zu lösen. Wenn Sie jedoch auf einen Fehler stoßen, der nur gelegentlich in der Produktion auftritt, wird es ziemlich viel Zeit in Anspruch nehmen, ihn durch das Hinzufügen von Logs und Ereignisverfolgung zu verfolgen.
Vor Jahren war ich für ein System verantwortlich, das jeden Tag gegen 1:00 Uhr morgens die Datenbankressourcen aufbrauchte und das gesamte System zum Absturz brachte. Damals überprüften wir die geplanten Aufgaben im Code während des Tages, und nachts wartete das Team darauf, dass der Bug in der Firma reproduziert wurde, und überprüfte dann den Betriebszustand der Untermodule, wenn er reproduziert wurde. Wir fanden die Ursache des Bugs erst in der dritten Nacht.
Meine Erfahrung ähnelt dem Hintergrund mehrerer Solaris-Systemingenieure, die Dtrace
entwickelt haben. Damals verbrachten die Solaris-Ingenieure auch Tage und Nächte damit, ein seltsames Produktionsproblem zu beheben, nur um festzustellen, dass es daran lag, dass eine Konfiguration falsch geschrieben wurde. Aber im Gegensatz zu mir beschlossen die Solaris-Ingenieure, dieses Problem ganz zu vermeiden, und erfanden Dtrace
, speziell für das dynamische Debugging.
Im Gegensatz zu statischen Debugging-Tools wie GDB
kann dynamisches Debugging Online-Dienste debuggen. Der gesamte Debugging-Prozess ist für das zu debuggende Programm nicht sensitiv und nicht invasiv, ohne den Code zu ändern, geschweige denn neu zu starten. Um es zu veranschaulichen, ist dynamisches Debugging wie eine Röntgenaufnahme, die den Körper des Patienten untersuchen kann, ohne Blutproben und Magenspiegelung zu benötigen.
Dtrace
war eines der ersten dynamischen Tracing-Frameworks, und sein Einfluss hat zur Entstehung ähnlicher dynamischer Debugging-Tools auf anderen Systemen geführt. Zum Beispiel haben die Ingenieure bei Red Hat Systemtap
auf Linux entwickelt, worüber ich als nächstes sprechen werde.
Systemtap
Systemtap
hat seine eigene DSL
, die verwendet werden kann, um Sondierungspunkte einzurichten. Bevor wir ins Detail gehen, lassen Sie uns Systemtap
installieren, um über das Abstrakte hinauszugehen. Hier verwenden wir einfach den Paketmanager des Systems zur Installation.
sudo apt install systemtap
Schauen wir uns ein hello world
-Programm an, das in Systemtap
geschrieben ist:
# cat hello-world.stp
probe begin
{
print("hello world!")
exit()
}
Sieht es nicht einfach aus? Sie benötigen sudo-Rechte, um es auszuführen.
sudo stap hello-world.stp
Es wird hello world!
ausgeben. In den meisten Szenarien müssen wir unsere eigenen stap
-Skripte nicht schreiben, um die Analyse durchzuführen, da OpenResty bereits viele fertige stap
-Skripte für die regelmäßige Analyse hat, die ich im nächsten Artikel vorstellen werde. Daher müssen wir heute ein kurzes Verständnis für stap
-Skripte haben.
Nach einiger Praxis zurück zu unserem Konzept: Systemtap
funktioniert, indem es das obige stap
-Skript in C umwandelt und den System-C-Compiler ausführt, um das Kernel
-Modul zu erstellen. Wenn das Modul geladen wird, aktiviert es alle Sondierungsereignisse, indem es den Kernel einhakt.
Zum Beispiel wird begin
am Anfang der Sondierung ausgeführt, und entsprechend end
, sodass das hello world
-Programm oben auch wie folgt geschrieben werden kann:
probe begin
{
print("hello ")
exit()
}
probe end
{
print("world!")
Hier habe ich nur eine sehr oberflächliche Einführung in Systemtap
gegeben. Frank Ch. Eigler, der Autor von Systemtap
, hat ein E-Book Systemtap tutorial geschrieben, das Systemtap
detailliert vorstellt. Wenn Sie mehr lernen und Systemtap
vertiefen möchten, empfehle ich, mit diesem Buch als besten Lernpfad zu beginnen.
Andere dynamische Tracing-Frameworks
Systemtap
reicht für Kernel- und Leistungsanalytiker nicht aus.
Systemtap
tritt standardmäßig nicht in den Systemkernel ein.- Es arbeitet auf eine Weise, die langsam startet und möglicherweise Auswirkungen auf den normalen Betrieb des Systems hat.
eBPF
(erweitertes BPF) ist eine neue Funktion, die in den letzten Jahren zum Linux-Kernel hinzugefügt wurde. Im Vergleich zu Systemtap
hat eBPF
den Vorteil der direkten Kernel-Unterstützung, keine Abstürze und schneller Start. Gleichzeitig verwendet es keine DSL
, sondern direkt C-Syntax, was den Einstieg viel einfacher macht.
Neben Open-Source-Lösungen ist auch Intels VTune
eines der besten Tools. Seine intuitive Benutzeroberfläche und Datenpräsentation ermöglichen es Ihnen, Leistungsengpässe zu analysieren, ohne Code zu schreiben.
Flame Graph
Schließlich erinnern wir uns an das Flame Graph, das im vorherigen Artikel erwähnt wurde. Wie wir bereits erwähnt haben, können die von Tools wie perf
und Systemtap
generierten Daten mit dem Flame Graph visueller dargestellt werden. Das folgende Diagramm ist ein Beispiel für ein Flame Graph.
Im Flame Graph sind die Farbe und Schattierung der Farbblöcke bedeutungslos, nur um eine einfache Unterscheidung zwischen verschiedenen Farbblöcken zu ermöglichen. Das Flame Graph ist eine Überlagerung der jedes Mal gesampelten Daten, sodass die Benutzerdaten die Breite und Länge der Blöcke sind.
Für das Flame Graph auf der CPU ist die Breite des Farbblocks der Prozentsatz der CPU-Zeit, die von der Funktion belegt wird: Je breiter der Block, desto größer der Leistungsverlust. Wenn es einen flach gedeckten Gipfel gibt, ist dies der Leistungsengpass. Die Länge des Farbblocks hingegen repräsentiert die Tiefe des Funktionsaufrufs, wobei der obere Block die laufende Funktion anzeigt und alle darunter liegenden Blöcke die Aufrufer dieser Funktion sind. Daher ist die Funktion unten der Supertyp der Funktion oben: Je höher der Gipfel, desto tiefer ist die Funktion aufgerufen.
Zusammenfassung
Es ist wichtig zu wissen, dass selbst eine nicht-invasive Technik wie dynamisches Tracing nicht perfekt ist. Es kann nur einen bestimmten individuellen Prozess erkennen; im Allgemeinen schalten wir es nur kurz ein, um die während dieser Zeit gesampelten Daten zu verwenden. Wenn Sie also über mehrere Dienste hinweg oder über längere Zeiträume hinweg erkennen müssen, benötigen Sie immer noch eine verteilte Tracing-Technik wie opentracing
.
Welche Debugging-Tools und -Techniken verwenden Sie in Ihrer regulären Arbeit? Hinterlassen Sie gerne einen Kommentar und diskutieren Sie mit mir, und teilen Sie diesen Artikel auch gerne mit Ihren Freunden, damit wir gemeinsam lernen und Fortschritte machen können.