Protokollierung und Abfrageverfolgung sind bewährte Methoden. Yandex-Bericht

Yandex.Market verfügt über eine große Microservice-Architektur. Die Browseranforderung auf der Hauptseite des Marktes führt zu Dutzenden eingebetteter Anforderungen in verschiedenen Diensten (Backends), die von verschiedenen Personen entwickelt werden. In einem solchen System kann es schwierig sein zu verstehen, aus welchem ​​Grund die Anfrage gefallen ist oder die Bearbeitung lange gedauert hat.


Anatoly Ostrovsky Megatolyaerklärt, wie sein Team dieses Problem gelöst hat und teilt marktspezifische Praktiken mit, die jedoch für jeden großartigen Service allgemein relevant sind. Sein Bericht basiert auf seinen eigenen Erfahrungen mit der Bereitstellung eines neuen Marktplatzes in relativ kurzer Zeit. Tolya leitete mehrere Jahre das Interface-Entwicklungsteam auf dem Markt und ist nun in Richtung unbemannter Fahrzeuge gewechselt.

- Alle unsere Marktplätze sind nach allgemeinen Grundsätzen gebaut. Dies ist ein großes einzelnes System. Wenn wir jedoch über das Frontend sprechen, sind die Anwendungen aus Sicht des Benutzers völlig unterschiedlich.



Gleichzeitig gehen unsere Frontends an viele Backends. Manchmal sind diese Backends einander ähnlich (verschiedene Instanzen derselben Anwendung). Und manchmal sind sie für den Service einzigartig (spezielle Abrechnung). Die Struktur eines solchen Systems kann als klassische Mikroservice-Architektur betrachtet werden.

Bei einem großen Dienst gibt es immer ein Problem - es ist schwer zu verstehen, was genau darin passiert. Oder zum Beispiel, was in dem Moment passiert, in dem ein Zahlungsfehler beim Benutzer auftritt. Angenommen, es ist gestern bei ihm passiert, und heute müssen wir verstehen, was passiert ist.



Backend 2 kann entweder für ein bestimmtes Produkt oder zu einem bestimmten Zeitpunkt oder für bestimmte Benutzer "brennen". Wir müssen in der Lage sein, auf jede Situation zu reagieren.



Wir haben viele Backends, und wie gesagt, sie können alleine laufen. Wenn dies in Form eines Diagramms dargestellt wird, wird es ziemlich verwirrend. Im wirklichen Leben kann es Hunderte von Mikrodiensten geben. Stellen Sie sich vor, wie viele Verbindungen zwischen ihnen bestehen werden.

Es gibt viele Schritte, um in dieses Thema einzutauchen. Ich werde kurz über jeden von ihnen sprechen.



Vereinbaren Sie zunächst mit Kollegen aus dem Backend ein gemeinsames Anforderungskennzeichnungssystem - es ist später einfacher, sie zu finden. Als nächstes müssen Sie in der Lage sein, das Problem schnell zu reproduzieren. Angenommen, ein Zahlungsfehler ist aufgetreten. Versuchen Sie schnell zu verstehen, wie es passiert ist und in welchem ​​Backend. Speichern Sie Protokolle nicht nur in Dateien, sondern auch in der Datenbank, damit Aggregationen durchgeführt werden können. Ein wichtiger Teil des Prozesses sind natürlich Grafiken und Überwachung. Als nächstes in der richtigen Reihenfolge.

Einheitliches Anforderungsidentifikationssystem




Dies ist eines der einfachsten Tools, um zu verstehen, was mit dem Service geschieht. Stimmen Sie mit Kollegen überein, dass Ihr Frontend beispielsweise eine Art ID-Anfrage (die requestId-Variable im Bild) generiert und diese dann in alle Endpunkte der Backends wirft. Und das Backend selbst erfindet nichts neu. Er nimmt die eingetroffene requestId und leitet sie in Anfragen an seine Backends weiter. Gleichzeitig kann er sein Präfix angeben, damit unter der identischen requestId dieses bestimmte Backend gefunden werden kann.



Wenn Sie also Ihre Protokolle verschlingen und sicherstellen, dass in Ihren Protokollen beispielsweise angegeben ist, dass das Backend fünfhundert ist, gibt es möglicherweise zwei Optionen. Sie geben diese Anforderungs-ID entweder an Ihre Kollegen weiter und sie sehen sie sich in ihren Protokollen an, oder Sie sehen es selbst.



Alle unsere Protokolle sind mit einer solchen ID gekennzeichnet, um nicht nur zu verstehen, was zu welchem ​​Zeitpunkt passiert ist, sondern auch um den Kontext dieser Anfrage beizubehalten. Es ist asynchron und kann später etwas zum Protokoll hinzufügen. Und wenn Sie auf Anfrage beißen, wird nichts Gutes daraus.

cURL


Um das Problem zu reproduzieren, verwenden wir das Dienstprogramm cURL. Dies ist ein Konsolendienstprogramm, das Netzwerkanforderungen stellt - http und https. cURL unterstützt viel mehr verschiedene Protokolle. Bei der Webentwicklung ist es jedoch einfacher anzunehmen, dass dies ein Tool für die Arbeit mit http (s) -Anfragen ist.



Um sich mit dem cURL-Team vertraut zu machen, können Sie zu einer beliebigen Site gehen, dann zu Network gehen und jede Anfrage in Form von cURL kopieren. Das Ergebnis ist eine so große Linie:



Wenn Sie versuchen, es herauszufinden, gibt es nichts, worüber Sie sich Sorgen machen müssen. Versuchen wir es auseinander zu nehmen.



Hier ist eine Anfrage an market.yandex.ru.



Hier wurde ein User-Agent hinzugefügt, der viel Platz beansprucht.



In der Tat ist der Rest Cookies. Es gibt ziemlich viele davon im Yandex-Code. In serialisierter Form sehen sie sehr beeindruckend aus. In der Tat gibt es nichts anderes als sie.

Wofür ist cURL also nützlich? Wenn Sie es in sich selbst kopiert und ausgeführt haben, haben Sie dieselbe Seite market.yandex.ru wie ich gesehen - nur der Computer, auf dem es ausgeführt wurde, wäre anders. Natürlich können einige Nebenwirkungen zu Unterschieden bei den IP-Adressen führen, aber im Allgemeinen handelt es sich um dieselben Anforderungen. Wir würden das gleiche Szenario reproduzieren.



Um solche cURL-Abfragen nicht jedes Mal zu erfinden, können Sie das Format-Curl des npm-Pakets verwenden.



Es werden alle Anforderungsparameter berücksichtigt, die die Funktion normalerweise verwendet - in diesem Fall nur Header und URL. Er weiß aber auch, wie man abfragt, textiert usw. Und die Ausgabe ist nur eine Zeichenfolge mit einer cURL-Anforderung.



Daher enthalten alle unsere Protokolle in der Entwicklungsumgebung auch cURL-Anforderungen.



Wir haben sogar Backend-cURL-Anfragen direkt im Browser protokolliert, um sofort zu sehen, wie wir zu unseren Backends gelangen, ohne auf die Browserkonsole zu schauen.



Bitte beachten Sie, dass cURL-Anfragen die Übertragung von Sitzungscookies beinhalten - dies ist schlecht. Wenn Sie Ihre cURL-Anfrage an market.yandex.ru an mich gerichtet haben, kann ich Ihren Market und jeden anderen Yandex-Service unter Ihrem Login eingeben. Daher speichern wir solche Anforderungen nirgendwo und protokollieren sie nur in Prüfständen für uns selbst - solche Daten können nicht verloren gehen.

Clickhouse


Als nächstes werde ich über strukturierte Protokolle sprechen. Hier werde ich die spezifische ClickHouse-Datenbank berücksichtigen, aber Sie können jede auswählen. ClickHouse ist ein säulenförmiges DBMS. Es ist bequemer, aus einer großen Datenmenge auszuwählen und große Datenmengen aufzunehmen. Es ist insofern gut, als Sie einen großen Teil des Protokolls darin speichern und dann beispielsweise eine Art Aggregation von einer Milliarde Datensätzen erstellen können.



In diesem Fall ist das ClickHouse-Auswahlbeispiel einfaches SQL. Hier zeigen wir die Anzahl der Anfragen nach Statuscodes für heute.



Infolgedessen werden wir 180.000 zweihundertsiebenhundert haben, und die verbleibenden Statuscodes zum Beispiel sind für uns nicht interessant. Aber wie können wir das interessant nutzen?



Wir können sagen, dass das Verhältnis von zweihundert zum Verhältnis der Gesamtzahl der Antworten der Service Level Indicator ist, der die Frage beantwortet, wie gut unsere Anwendung in Bezug auf Statuscodes funktioniert. Obwohl einfach, spricht er bereits über etwas.



Basierend auf unserem Indikator können wir den ersten SLI erstellen, dh zum Beispiel, dass 99% unserer Anfragen in Ordnung sein sollten. Und hier können wir vergleichen, dass wir unseren SLI durchgeführt haben. Wenn sie nicht erfüllt worden wären, hätten wir versuchen können, entweder einige letzte Anfragen zu erkennen, die fünfhundert gewesen wären, oder einfach nur kritische Dinge.



Zum Beispiel sind Zahlungsfehler für uns kritisch, aber in diesem Fall geben sie Null zurück - es ist ein Glück :)



Wie stellen Sie sicher, dass Ihre Protokolle in dieser praktischen Form vorliegen und über SQL erstellt werden können?



Dies ist ein Thema für einen separaten großen Bericht, und alles hängt von Ihrer Infrastruktur ab. Es scheint jedoch zwei Möglichkeiten zu geben. Erstens: Senden Sie Metadaten direkt an die Laufzeit, direkt an die Datenbank. Wir machen es auf die zweite Weise anders: Wir folgen der Protokolldatei und senden Chunks entweder in der Datenbank oder an einer Zwischenstelle.

Dies funktioniert für uns eher vielschichtig - wir senden Protokolle von einer bestimmten Instanz an einen Remotespeicherserver solcher Protokolle.

Trace anfordern


Es gibt kein Konzept für die "Abfrageverfolgung". Dieser Begriff wurde von Google geprägt.



Wenn Sie im Internet nach "Abfrageverfolgung" suchen, wird der Befehl traceroute angezeigt. Möglicherweise ähnelt dies der Abfrageverfolgung.



Es gibt sogar ein Konsolenprogramm, und hier habe ich es für die Website bringly.ru ausgeführt (ein Dienst, den wir im letzten Frühjahr entwickelt haben). Es ist hilfreich zu verstehen, welche Art von Maschinen und Servern die Anforderung durchläuft, bevor sie an den Balancer gelangt, der entweder mit dem Layout oder mit etwas anderem antwortet.



Hier ist unser Balancer. Mit Abfrageverfolgung meinen wir nicht dies, sondern alles, was in unserem Balancer passiert - wie die Anforderung weiter in unserer Anwendung node.js lebt.



Wir sehen dies in Form einer Zeitleiste, in der die horizontale Zeit und die vertikale Reihenfolge der Anforderungen angezeigt werden. In diesem Fall haben wir eine Anfrage an die Produktkarte, wobei ersichtlich ist, dass dies eine Anfrage an das Backend unserer Autorisierung ist. Nach seiner Entscheidung gingen drei lange Schlangen - dies ist eine Anfrage an unser Haupt-Backend nach einem Warenkorb, einer Produktkarte und ähnlichen Produkten. Wir haben also eine Spur.



Hier sehen Sie den gleichen Antrag auf Autorisierung, und dann ging das Backend. In diesem Fall verhält sich das Backend nicht sehr optimal, da es viele aufeinanderfolgende Abfragen in seiner Datenbank hat. Wahrscheinlich könnte eine solche Abfrage optimiert werden.



Und hier ist ein Beispiel für eine Ablaufverfolgung, bei der wir kein Backend aufgerufen haben, sondern sofort den Status 500 angegeben haben. Wie ist eine solche Ablaufverfolgung für uns nützlich? Wir müssen Kollegen nicht stören. Wir haben die ID dieser Anfrage, sodass wir selbst in den Protokollen nachsehen und herausfinden können, was passiert.



Hier ist die gegenteilige Situation. Backend sagte, dass etwas nicht stimmte und schrieb gleichzeitig in die Meta-Informationen, was genau passiert ist - eine Art Stack-Trace erschien.



Wie mache ich das gleiche Werkzeug?

Das Wichtigste hier ist die Datenbank. Wenn Sie das einfachste "INSERT INTO" in der Datenbank einiger Aktionen mit dem Dienst haben, können Sie später zumindest SQL verwenden, um die erforderlichen Ereignisse zu finden. Und wenn nötig, können Sie eine Schnittstelle dazu erstellen.

Grafiken


Dies ist ein sehr interessantes Thema, auf das ich heute natürlich nicht näher eingehen werde :)



Lassen Sie uns über die Protokollierung sprechen. Wir haben viele Grafiken, wir schauen sie uns an, wenn wir etwas ausrollen - und in den Timings gibt es so ein Rauschen.



Diagramme helfen visuell zu erkennen, dass etwas nicht stimmt. Und dann müssen Sie sich noch die Protokolle ansehen und verstehen, was mit ihnen nicht stimmt. In diesem Fall bedeutet der Anstieg unmittelbar nach der Freigabe zumindest, dass eine solche Freigabe sofort zurückgesetzt werden muss.

Überwachung


Ein noch wichtigerer Teil und ein stärkeres Eintauchen in dieses Thema ist die Überwachung. Unter Überwachung verstehe ich zum einen die automatische Überwachung von Diagrammen und zum anderen alle automatisierten Regeln für die Überwachung von Objekten.



Wir überwachen das Verhältnis von fünfhundert zur Gesamtzahl der Antworten pro Minute. Wir überwachen auch vierhundert, das Vorhandensein einer Last auf dem Dienst, überprüfen den Integritätsprüfungsknopf, der den Ping-Knopf jedes der Backends zieht, usw.



Darüber hinaus verfügen wir über Überwachungs-Dashboards, die wir auf Bildschirmen in der Nähe von Workstations einfügen. So sehen wir sofort, welche der Überwachung "erröten". Zum Beispiel ist es hier eines der wichtigsten, bei denen das Frontend und unser Haupt-Backend sichtbar sind. Hier können Sie sehen, dass einige Überwachung im Backend aufleuchtet. Dies bedeutet, dass die für diesen Dienst verantwortliche Person in diesem Moment eine Nachricht per Telegramm erhält oder sie sogar anruft - dies hängt von den Überwachungseinstellungen ab.

Zusammenfassung


Mit einer einzigen requestId können Sie Probleme in einem Dienst, der aus mehreren Anwendungen besteht, leichter finden. Mit der richtigen cURL können Sie die Probleme genauer reproduzieren und sehen, wie Sie beispielsweise selbst Daten an das Backend senden. Mit strukturierten Protokollen können Sie SLI erstellen, und sie sind bequemer zu verwenden als normale Textprotokolle. Und vergessen Sie nicht, den Tabellen zu folgen und die Überwachung durchzuführen.

Ich empfehle, das Buch Site Reliability Engineering von Google zu lesen, wenn Sie an Infrastruktur interessiert sind.

All Articles