Hallo! Ich heiße Pasha Tschernjak, ich bin leitender Entwickler bei QIWI, und heute möchte ich über das Unvermeidliche sprechen. Über Legacy.
Fangen wir mit der Frage an: Was ist ein Legacy-Service? Ein Legacy-Service ist ein Dienst, mit dem der Entwickler seit einer Woche/Monat/Jahr nichts mehr zu tun hatte? Oder ist es ein Dienst, der von einem weniger erfahrenen Programmierer, zum Beispiel von Ihnen, vor einem Jahr geschrieben wurde? Aber mittlerweile sind Sie besser und erfahrener. Oder bedeutet Legacy-Service, dass Sie beschlossen haben, diesen Dienst nie wieder zu committen und langsam eine Ablösung dafür vorbereiten? In jedem Fall ist es eine Zeitbombe, einen solchen Dienst unbeaufsichtigt zu lassen und nicht zu aktualisieren.
Bevor ich dazu übergehe, wie wir bei QIWI mit unseren Legacy-Services arbeiten, möchte ich erklären, wie wir Ordnung bei den Diensten im Wallet geschaffen haben. Seit zwei Jahren bin ich für die Funktionalität verantwortlich. Wenn es ein Problem gibt, rufen sie immer zuerst mich an. Ich habe normalerweise nicht die Dreistigkeit, um 23 Uhr jemanden anders anzurufen, also musste ich mich setzen und mich mit allen Diensten in unserem Bereich befassen.
Aber ich, wie jeder andere Mensch, liebe es, nachts zu schlafen, also habe ich versucht, das Betriebsklima zu klären: „Leute, warum ruft ihr mich an?“. Darauf bekam ich eine recht knappe Antwort: „Wen sonst?“. Denn ich repariere die Dienste, und die Leute wissen schlichtweg nicht, an wen sie sich wenden sollen.
Deshalb haben wir auf einer der Retrospektiven des Backend-Teams des Wallets beschlossen, eine Tabelle zu erstellen, auf der eine Liste unserer Dienste, Mikrodienste und Monolithen des Wallets sowie die Verantwortlichen dafür vermerkt sind. Tabellen sind im Allgemeinen nützlich, in einem vernünftigen Rahmen.
Neben den Informationen darüber, wer wofür verantwortlich ist, gab es auch Antworten auf Fragen: Wer ist der Besitzer des Dienstes, wer ist für dessen Entwicklung, Architektur und Lebenszyklus verantwortlich. Die Personen, die für diesen Dienst verantwortlich sind, sind die, die ihn im Bedarfsfall reparieren können. Der Dienstbesitzer hat das Recht, +2 in den Commits zu lassen, die Verantwortlichen müssen ebenfalls unbedingt beim Review anwesend sein, bevor dieser Dienst einen neuen Commit übernimmt.
Die Zeit verging, neue Praktiken wurden angewendet, wie zum Beispiel die Migration zu Kubernetes, verschiedene checkstyle, spotbugs, ktlint, das Vorhandensein von Logs in Kibana, die autodiscovery von Diensten anstelle der direkten Angabe von Adressen und andere nützliche Dinge. Und überall ermöglichte unsere Tabelle es, die Aktualität unserer Dienste aufrechtzuerhalten. Für uns ist das eine Art Checkliste, die besagt, dass dieser Dienst das kann, und das noch nicht. Aber wir gingen weiter, erkannten, dass uns Informationen über unsere Dienste fehlten, die wir überwachten, wo die Quellcodes des Dienstes lagen, wo die Aufgaben zum Bauen in TeamCity gestartet werden, wie sie deployt werden, wo die Quellcodes der End-to-End-Tests gespeichert sind, Fotos von Grooming über die Architektur und über getroffene Entscheidungen. Ideal wäre es, wenn all diese Informationen irgendwo hinterlegt wären und zur Hand, wenn man sie braucht. Deshalb wurde unsere Tabelle zum Ausgangspunkt für die Suche nach Informationen.
Aber QIWI, obwohl es den Geist eines Startups bewahrt, ist ein großes Unternehmen. Wir sind bereits 12 Jahre alt und die Teams ändern sich: Menschen gehen, Menschen kommen, es bilden sich neue Teams. Und wir fanden auf unserer Domain mehrere Dienste, die uns vererbt wurden. Einige kamen von Entwicklern aus anderen Teams, andere hatten einfach indirekt mit dem Wallet zu tun, deshalb wird dieser Dienst jetzt in unserem Portfolio geführt. Warum sollten wir uns darum kümmern, was und wie funktioniert? Der Dienst funktioniert ja, und wir haben Produktfeatures, die unbedingt umgesetzt werden müssen.
Wie es manchmal der Fall ist.
Aber irgendwann entdecken wir, dass der Dienst seine Funktion nicht mehr erfüllt, dass etwas kaputt ist – was tun wir in so einer Situation? Der Dienst funktioniert einfach nicht mehr. Gar nicht. Und erfahren haben wir das, erstens zufällig und zweitens nach sechs Monaten. So ist es. Das einzige, was wir wussten – auf welchen virtuellen Maschinen der Dienst läuft, wo seine Quellcodes liegen, und das war's. Wir machen ein git clone und tauchen ein in die Gedanken einer Person, die das vor ein paar Jahren geschrieben hat, aber was sehen wir? Nichts von dem gewohnten Spring Boot, auch wenn wir an alles gewöhnt sind, schließlich sind wir full stack und so weiter. Vielleicht gibt es dort Spring Framework? Aber das gibt es nicht.
Der Junge, der all dies geschrieben hat, war streng und hat alles in reinem Java geschrieben. Gewöhnliche Entwicklerwerkzeuge gibt es nicht, und die Idee kommt auf – das Ganze müsste man umschreiben. Wir haben schließlich Mikrodienste, und aus jedem Toaster dringt das vertraute "Leute, Mikrodienste sind das, was ihr braucht!". Wenn irgendetwas nicht stimmt, könnt ihr in Ruhe jede Sprache wählen und alles wird gut.
Die Sache ist die, dass wir derzeit keinen Auftraggeber haben, der für diesen Dienst verantwortlich ist. Welche Geschäftsanforderungen hatte er, was soll dieser Dienst überhaupt tun? Der Dienst ist eng in eure Geschäftsprozesse integriert.
Und jetzt sagt mir, wie einfach es ist, einen Dienst neu zu schreiben, ohne seine Geschäftsanforderungen zu kennen? Es ist unklar, wie der Dienst protokolliert wird, ob es Metriken gibt – unbekannt. Welche sie sind, falls es sie gibt – erst recht unbekannt. Und dabei gibt es im Dienst eine riesige Anzahl von Klassen mit unklarer Geschäftslogik. Etwas gelangt in eine Datenbank, über die wir auch bisher nichts wissen.
Wo soll man anfangen?
Mit dem naheliegendsten — der Verfügbarkeit von Tests. Dort ist normalerweise zumindest eine gewisse Logik geschrieben und man kann Schlüsse darüber ziehen, was vor sich geht. Momentan ist TDD in Mode, aber wir sehen, dass es vor 5 Jahren fast genau so war wie jetzt: es gibt kaum Unit-Tests, und die sagen uns überhaupt nichts. Nun, außer vielleicht einer Überprüfung, wie man irgendein XML mit einem benutzerdefinierten Zertifikat signiert.
Wir konnten aus dem Code nichts herauslesen, und wir schickten jemanden, um zu sehen, was dort auf der virtuellen Maschine los ist. Wir öffneten die Dienstprotokolle und fanden darin den Fehler des HTTP-Clients, das selbstsignierte Zertifikat, das in die Anwendungsressourcen integriert war, war völlig veraltet. Wir nahmen Kontakt mit unseren Analysten auf, sie baten um ein neues Zertifikat, das uns ausgestellt wurde, und der Dienst funktioniert wieder. Man könnte denken, dass es damit erledigt ist. Oder nicht? Der Dienst funktioniert schließlich und erfüllt eine Funktion, die für unser Geschäft notwendig ist. Wir haben bestimmte Standards für die Entwicklung von Anwendungen, die vermutlich auch bei Ihnen bestehen. Zum Beispiel sollten Protokolle nicht auf der Node im Ordner gespeichert werden, sondern in einem Speicher, wie zum Beispiel Elastic, und wir sollten sie in Kibana betrachten. Man könnte auch von den wichtigsten Metriken sprechen. Das heißt, die Belastung des Dienstes, die Anzahl der Anfragen an den Dienst, ob er lebt oder nicht, wie es mit seinem HealthCheck aussieht. Zumindest helfen diese Metriken zu entschlüsseln, wann man ihn mit ruhigem Gewissen außer Betrieb nehmen und als schlechten Traum vergessen kann.
Was tun
Deshalb fügen wir diesen alten Dienst in die Tabelle ein, und dann suchen wir aus den Entwicklern Freiwillige, die sich um den Dienst kümmern und ihn in Ordnung bringen: Sie schreiben wenigstens ein paar Informationen über den Dienst, fügen Links zu den Dashboards in Grafana, zu den Build-Tasks hinzu und verstehen, wie die Anwendung bereitgestellt wird; man kann die Dateien nicht einfach per FTP zusammensammeln.
Das Wichtigste ist, wie viel Zeit all diese nützlichen freiwilligen Aktivitäten in Anspruch nehmen wird? Ein Sprint für einen mehr oder weniger erfahrenen Entwickler, zum Beispiel während 20 % der technischen Schulden. Und wie viel Zeit wurde darauf verwendet, die verfestigte Logik im Umgang mit einem gewissen Regierungssystem zu verstehen und auf aktuellere Technologien umzustellen? Davon kann ich nicht garantieren, vielleicht ein Monat, vielleicht auch zwei Monate Teamarbeit. Das sage ich aus Erfahrung mit der aktuellen Integration eines neuen Dienstes.
Dabei gibt es keinen geschäftlichen Nutzen. Gar keinen. Es ist in Ordnung, einen Dienst zu unterstützen und dafür etwas Zeit zu investieren. Aber nach unseren üblichen Tanzrunden mit dem Dienst haben wir ihn in die Tabelle aufgenommen, Informationen über ihn hinzugefügt und möglicherweise werden wir ihn irgendwann neu schreiben. Aber im Moment erfüllt er unsere Standards für die Arbeit mit Diensten.
Zusammenfassend möchte ich zu einem gewissen Plan kommen, was mit Legacy-Diensten zu tun ist.
Legacy vollständig neu zu schreiben, ist eine schlechte Idee.
Im Ernst, darüber muss man sich nicht einmal Gedanken machen. Es ist klar, dass es wünschenswert wäre und einige Vorteile sichtbar sind, aber in der Regel ist das für niemanden notwendig, einschließlich Ihnen selbst.
Verzeichnis
Graben Sie die Quellcodes Ihrer Anwendungen aus, erstellen Sie ein Verzeichnis, in dem steht, was wo liegt und wie es funktioniert, und fügen Sie auch eine Projektbeschreibung (eine Art readme.md) hinzu, um schnell zu verstehen, wo die Logs und Metriken liegen. Der Entwickler, der damit nach Ihnen arbeitet, wird Ihnen nur danken.
Verstehen Sie die Domain
Wenn Ihnen eine Domain gehört, versuchen Sie, den Überblick zu behalten. Das klingt banal, ja, aber nicht jeder achtet darauf, dass die Dienste einheitlich sind. Tatsächlich ist es viel einfacher, nach einem einheitlichen Standard zu arbeiten.
Nur registrierte Benutzer können an der Umfrage teilnehmen. .
Was machen Sie mit Ihrem Legacy?
31.5%Ich schreibe alles von Grund auf neu, so ist es richtig12
52.6%Fast das Gleiche wie Sie20
10.5%Wir haben kein Legacy, wir sind gut4
5.2%Ich werde es in den Kommentaren schreiben2
38 Benutzer haben abgestimmt. 20 Benutzer haben sich enthalten.
Quelle: habr.com
