Zum Thema Leistung alter und neuer Versionen eines Knotens

Von Zeit zu Zeit haben Entwickler, die alte Knotenanwendungen unterstützen, Zweifel an der Notwendigkeit, die Anwendung von alten Versionen auf neue Knoten zu übertragen. Das Hauptargument für die Beibehaltung der alten lautet: "Ich verwende keine neuen Funktionen, aber ihre Implementierung wird die Verarbeitung insgesamt sicherlich verlangsamen." Darüber hinaus kann die Situation durch das Vorhandensein von Abhängigkeiten von Bibliotheken, die unter neuen Knoten nicht mehr unterstützt werden, erheblich kompliziert werden, und eine Änderung der Version eines Knotens führt automatisch zu einer erheblichen Verarbeitung der Anwendungsarchitektur. Ich hoffe, mein Artikel wird ihnen helfen, sich für dieses Problem zu entscheiden.

Bevor Sie beginnen, erinnere ich Sie an das Grundprinzip des IT-Geschäfts: ARBEITEN, NICHT BERÜHREN!

Wenn Ihre Anwendung ordnungsgemäß funktioniert, die Aufgaben vollständig bewältigt werden und keine dringende Notwendigkeit für ihre Verarbeitung besteht, ist es besser, alles so zu belassen, wie es ist. Recycling kann ein sehr schmerzhafter und langwieriger Prozess sein. Infolgedessen erhalten Sie keine konkreten Vorteile außer einem Gefühl der ästhetischen Zufriedenheit, und zu diesem Zeitpunkt wird Ihr Unternehmen darunter leiden.

Mein Artikel ist für diejenigen, die noch ein Bedürfnis haben. Ich werde meine jüngste Situation beschreiben, über die Schwierigkeiten bei der Lösung sprechen und die Ergebnisse angeben, die ich letztendlich erhalten habe.

Ich entwickle ein System zum Sammeln und Verarbeiten von Protokollen anderer Anwendungen. Etablierte Workloads - Hunderttausende von Protokollen pro Minute und Komponente. Das System war horizontal gut skalierbar, hatte eine modulare Architektur, arbeitete mehr als ein Jahr erfolgreich und bewältigte seine Funktionen insgesamt. Die verwendete Version des Knotens ist 0.10

Was hast du vor?

Natürlich kein Mangel an Funktionalität. Die neuen es6-Funktionen wurden nicht einmal als Argument angesehen. Natürlich machen sie das Leben ein bisschen schöner, aber nichts weiter. Für jede unserer Aufgaben war die Funktionalität des alten Knotens völlig ausreichend. Probleme traten an der unerwartetsten Stelle auf, als die Funktionalität komplexer wurde.

Problem Eins:

Eine der Komponenten mit Spitzeneintrittslasten und Speicherverbrauch unter 5 GB wurde plötzlich höllisch langsamer. Das Problem trat nicht jedes Mal spontan auf, normalerweise gegen Ende des Peaks. Wenn die Anwendung keine Zeitüberschreitungen aufwies, erholte sich die Leistung allmählich innerhalb einer halben oder einer Stunde. Neustart sofort behoben.

Nach dem "Deep Debugging" -Prozess stellte sich heraus, dass der gesamte Prozess langsamer wird, sogar synchrone Vorgänge, weshalb der Schluss gezogen wurde, dass der Garbage Collector selbst "schlechter" wurde. Was dagegen zu tun war, war völlig unklar. Die einzige Lösung bestand darin, den Verlauf der Änderungen in unserem Code mehrere Monate lang zu durchsuchen und wichtige Funktionen zurückzusetzen. Andererseits trat das Problem nicht oft und nicht jeden Tag auf, und ein manueller Neustart des Systems schien ebenfalls eine völlig akzeptable Lösung zu sein (manuell bedeutet ein Skript auf der Grundlage des Rückstandsdetektorsignals). Wir waren eher zur zweiten Option geneigt. Und wenn nicht das zweite Problem gewesen wäre, wäre es höchstwahrscheinlich implementiert worden.

Das zweite Problem:

Eine weitere unserer Komponenten war, viel Speicher zu verbrauchen. Da diese Komponente tatsächlich ein Cache war, war ihre „Gier“ im Prinzip erklärbar. Bis zu dem Zeitpunkt, als es erforderlich war, es von oben auf ein genau festgelegtes Volumen zu beschränken. Und dann stellte sich heraus, dass die Komponente an Speicher gewann und es nicht eilig hatte, sie weiterzugeben. Und sogar mit fast Leerlaufdrehzahl arbeiten. Das heißt, zum Zeitpunkt der Spitzenlast wählte der Knotenspeichermanager den maximalen Speicher und sogar mit einem Rand aus und hielt ihn dann bis zum Ende des Jahrhunderts (z. B. Neustart der Komponente). Ich werde gleich erwähnen, dass die Leckoption natürlich geprüft und verifiziert wurde. Leider gab es keine Lecks und wieder waren wir in einer Sackgasse.

Ich habe an verschiedenen Stellen im Internet versucht, die Speicherverwaltung eines Knotens durchzuführen und unsere Situation zu lösen. Als Antwort erhielt ich jedoch nur viel Negativität in Bezug auf die Verwendung des 0.10-Knotens. Im Allgemeinen war es diese Negativität, die mich dazu brachte, zu den neuesten Versionen des Knotens zu wechseln.

Was hielt zurück?

1. Angst vor Produktivitätsverlust.

Diejenigen, die an Python gearbeitet haben, erinnern sich, dass der Übergang von der 2.x- zur 3.x-Linie mit einem erheblichen Produktivitätsverlust einherging. Ich weiß nicht, wie die Dinge in Python jetzt sind, vielleicht hat sich die Situation verbessert. Es ist jedoch logisch zu erwarten, dass der Knoten nach dem Hinzufügen all dieser neuen Funktionen zu es6 auch solide sinken könnte. Ich habe versucht, einige Benchmarks zu googeln, um neue Knoten mit alten zu vergleichen. Ich fand nichts Sinnvolles.

2. Leistung JSON.parse

Da wir mit Protokollen arbeiten, nimmt JSON.parse den Löwenanteil des Prozessors ein. Zu einer Zeit haben wir es mit verschiedenen Versionen des Knotens verglichen und einen Leistungsabfall von etwa 30% erzielt. Der 4.x-Knoten wurde mit 0,10 und 0,12 verglichen.

Tatsächlich waren diese Gründe nicht entscheidend, da der Prozessor kein Engpass war. Zusätzlich gibt es für solche Aufgaben eine horizontale Skalierung.

3. Paketabhängigkeiten

Aber das war ein Stolperstein. Unsere zentralste komplexeste Komponente verwendete das libmysqlclient-Paket, das nur unter Knoten 0.10 funktioniert. Schlimmer noch, seine synchronen Anrufe. Das heißt, es war unmöglich, den MySQL-Treiber einfach zu ändern und einen Aufruf durch einen anderen zu ersetzen, ohne die Komponentenarchitektur von teilweise synchron zu vollständig asynchroner Verarbeitung zu verarbeiten. Darüber hinaus war der schwierigste Teil dieser Aufgabe nicht die Verarbeitung selbst, sondern vielmehr die Frage, wie das Management seine Bedürfnisse rechtfertigen und zeigen kann, was genau es dem Projekt geben würde :)

Was gab?

Infolgedessen sind wir immer noch vom Knoten 0.10 zum letzten lts 8.11.x übergegangen

1. Kein Leistungsabfall. Im Gegenteil, wir haben eine Steigerung in der Größenordnung von 10-15% erhalten.
2. Deutlich verbesserter Speicherverbrauch, je nach Komponente ca. 30-50%
3. Die oben angesprochenen „unlösbaren“ Probleme wurden von selbst gelöst
4. Wir haben endlich die Möglichkeit, neue Funktionen von es6 zu nutzen! Obwohl aus Gewohnheit, verwenden wir sie noch nicht)))

Source: https://habr.com/ru/post/de413673/


All Articles