Microservices: Wie wird der Vertrag eingehalten?

Der Übergang zur Microservice-Architektur erfordert eine Überarbeitung des Konzepts für Entwicklung, Test, Wartung und Design, dh aller Aspekte des Lebenszyklus von Softwarekomponenten. In diesem Beitrag werden wir über die Vorgehensweisen sprechen, zu denen das Acronis-Architektenteam gekommen ist, um die besten Komponenten-APIs zu entwickeln. Die Geschichte wird sowohl die Beschreibung des Problems als auch die Analyse seiner Lösungen enthalten. Vielleicht wird dieser Beitrag einigen als „Kapitän“ erscheinen, für jemanden ist nicht klar, warum er die Superlösung X verpasst hat, aber wir hoffen, dass er für Sie interessant und nützlich ist. Wir laden Microservice Builder ein, Ihre Kommentare unter cat zu lesen und zu hinterlassen.

Bild

Wenn Sie unseren Blog abonniert haben, haben Sie bereits etwas über Mikroserviceverträge gelesen. Wir haben darüber in Beiträgen über die Auswahl von Swagger oder RAML gesprochen sowie über statische Überprüfungen , die auf der Grundlage von zuvor erstellten Anmerkungen durchgeführt werden können. Der Grund für den heutigen Beitrag war ein Bericht auf der HighLoad-Konferenz . Wir mussten allgemein über den Weg sprechen, den wir gegangen sind, um die Beziehung zwischen Microservices zu formalisieren. Und heute möchte ich unsere Schlussfolgerungen mit Habr teilen und auch prüfen, ob andere Architekten uns zustimmen.

Microservices sind die "Bausteine", aus denen Entwickler moderne Anwendungen erstellen. Jeder dieser Dienste interagiert über eine API mit der Außenwelt. In der Regel werden Mikrodienste von getrennten Teams entwickelt, die manchmal geografisch verteilt sind. Für eine effektive Arbeit ist es daher erforderlich, die Konsistenz und Integrität ihrer öffentlichen Schnittstellen zu gewährleisten. In großen Unternehmen mit Hunderten von Diensten ist eine Anmerkung zu jeder Komponente erforderlich: Formalisieren Sie die Eingabedaten und beschreiben Sie die Ergebnisse ihrer Arbeit ausführlich. Wenn Sie mit HTTP REST arbeiten, gibt es hierfür zwei gängige Anmerkungsformate: RAML und Open API Specification (auch bekannt als Swagger). Die Fragen, auf die wir uns heute konzentrieren, sind jedoch nicht an ein bestimmtes Protokoll gebunden. Daher ist das Folgende auch für gRPC relevant.

Hintergrund


Acronis gibt es seit über 15 Jahren. In dieser Zeit haben sich die Produkte und die Codebasis erheblich weiterentwickelt. Aus einer komplexen Desktop-Anwendung ist ein Unternehmensmodell mit zentralisierten Verwaltungskonsolen, Rechtebegrenzung und Überwachungsprotokollen entstanden. Der nächste Schritt war die Umwandlung der Unternehmensanwendung in eine offene Plattform, auf der die gesammelten Erfahrungen für die Integration mit externen Diensten genutzt wurden.

War die API früher wichtig, ist sie heute ein wichtiger Bestandteil des Produkts. Und die Prozesse, die diese API bereitstellt, sind ausgereift.

Wichtige Probleme


Die Probleme bei der API-Erstellung sind allen bekannt. Wir werden sie in hypertrophierter Form beschreiben: als Schmerzen, die einen hypothetischen Programmierer Vasya und seinen nicht weniger hypothetischen Manager Kolya quälen. Alle Namen sind fiktiv und Übereinstimmungen sind nicht zufällig :)

1. Beschreibung ist veraltet

Lassen Sie den Programmierer Vasya die Komponente A entwickeln, die die API der Komponente B verwendet. Diese hat eine Anmerkung, ist aber ungültig. Vasya muss sich in den Code eines anderen kriechen, nach Leuten suchen, Fragen stellen. Die Fristen rücken heraus, und sein Manager Kolya muss sich um die Übergabe von Fristen kümmern.

2. API ist nicht konsistent

Der Programmierer Vasya hat die Aufgabe abgeschlossen und ist zur nächsten übergegangen, die sich auf die Funktionsweise von Komponente B bezieht. Sowohl die Entwickler B als auch die Entwickler C haben jedoch ein unterschiedliches Schönheitsgefühl, sodass in der API dieselben Aktionen unterschiedlich ausgeführt werden. Vasya hat sich erneut mit dem Code befasst, und Kolya leidet erneut unter der Nichteinhaltung von Fristen.

3. API nicht dokumentiert

Der Manager von Kolya beschließt, die API der Komponente A zu veröffentlichen, damit Integratoren wunderbare Integrationen vornehmen können. Integratoren stehen vor Problemen, der Support-Service ist überlastet, bei Manager Kolya brennt alles und Vasya glaubt, dass er bald an der Reihe sein wird.

4. Die API ist nicht mit der alten Version kompatibel.

Integrationen werden implementiert, alle Brände gelöscht. Aber Vasya entscheidet plötzlich, dass die API seiner Komponente alles andere als perfekt ist und in eine Überarbeitung eintaucht. In diesem Fall wird natürlich die Abwärtskompatibilität verletzt und alle Integrationen fallen auseinander. Diese Situation führt zu Kosten für die Integratoren und zu Geldverlusten für die Entwicklungsfirma.

Behandlungsmethoden


All diese Probleme treten auf, wenn Programmierer keine Ahnung von einer guten REST-API haben oder diese Ansicht fragmentiert ist. In Wirklichkeit haben nicht alle Entwickler Erfahrung mit REST. Und deshalb zielen die Hauptmethoden der „Behandlung“ auf Bildung ab. Wenn die Vision der richtigen API, die mit der Vision anderer Entwickler, Architekten und Dokumentarfilmer abgestimmt ist, im Kopf jedes Entwicklers zu zermürben beginnt, wird die API ideal. Der Prozess der Herausbildung dieser Vision erfordert Anstrengungen und spezielle Werkzeuge, über die wir jetzt sprechen werden.

Schmerz 1. Annotation entspricht nicht der Implementierung


Anmerkungen können vom aktuellen Status des Dienstes abweichen, nicht nur, weil es sich um eine API der „dunklen Vergangenheit“ handelt, die nicht erreicht werden kann. Es kann auch eine vielversprechende zukünftige API sein, die noch nicht eingetroffen ist.

Der Grund für diese Bedingungen ist das mangelnde Verständnis dafür, warum Anmerkungen erforderlich sind. Ohne Terror seitens der Architekten neigen die Entwickler dazu, Annotation als internes Hilfswerkzeug zu betrachten, und implizieren nicht, dass jemand außerhalb es verwenden wird.

Sie können diesen Schmerz heilen, indem Sie:

  • Überprüfung der Architektur. Eine sehr nützliche Sache für Unternehmen jeder Größe, in denen es mindestens einen Programmierer gibt, der „weiß, wie man es richtig macht“. Wenn der Dienst geändert wird, sollte der Architekt oder die verantwortliche Person den Status der Anmerkungen überwachen und die Programmierer daran erinnern, dass nicht nur der Dienst, sondern auch seine Beschreibung aktualisiert werden müssen. Nebenwirkungen - ein Engpass gegenüber dem Architekten
  • Codegenerierung aus Anmerkungen. Dies ist der sogenannte API-First-Ansatz. Dies bedeutet, dass Sie zunächst eine Anmerkung erstellen, dann den Primärcode generieren (es gibt genügend Tools dafür, z. B. [go-swagger] (https://github.com/go-swagger/go-swagger)) und dann den Business-Service ausfüllen Logik. Diese Anordnung vermeidet Inkonsistenzen. Es funktioniert gut, wenn der Bereich der vom Dienst gelösten Aufgaben klar abgegrenzt ist.
  • Testen von Anmerkungen im Vergleich zur Implementierung . Dazu generieren wir aus der Annotation (RAML / swagger) den Client, der den Service mit Requests bombardiert. Wenn die Antworten der Anmerkung entsprechen und der Dienst selbst nicht abfällt, ist alles in Ordnung.

Test Annotation vs Implementierung
Bleiben wir beim Testen. Eine solche vollautomatische Abfrageerzeugung ist eine komplexe Aufgabe. Mit Daten aus API-Anmerkungen können Sie separate Anforderungen erstellen. Jede API impliziert jedoch Abhängigkeiten. Bevor Sie beispielsweise GET / clients / {cliend_id} aufrufen, müssen Sie zuerst dieses Objekt erstellen und dann seine ID abrufen. Manchmal sind Abhängigkeiten weniger explizit. Zum Erstellen eines Objekts X muss der Bezeichner des zugeordneten Objekts Y übergeben werden. Dies ist keine Unterauflistung. Weder RAML noch Swagger erlauben die Beschreibung expliziter Abhängigkeiten. Daher sind hier mehrere Ansätze möglich:

  1. Erwarten Sie formelle Kommentare von Entwicklern in Anmerkungen, die auf Abhängigkeiten hinweisen.
  2. Um eine Beschreibung der erwarteten Sequenz von den Entwicklern anzufordern (es gibt einige Möglichkeiten, Anforderungen mit YAML , spezialisiertem DSL oder über eine schöne GUI zu beschreiben, wie dies der jetzt verlassene Apigee getan hat) .
  3. Reale Daten erfassen (z. B. mit OpenResty alle Serveranforderungen und -antworten protokollieren )
  4. Abhängigkeiten aus Annotationen mit (fast) künstlicher Intelligenz extrahieren (z. B. RESTler )

In jedem Fall ist die Testaufgabe sehr zeitaufwändig.

Bild

Persönlich kamen wir zu dem Punkt, Testsequenzen manuell vorzubereiten. In jedem Fall müssen Entwickler Tests schreiben, damit wir ihnen ein praktisches Tool zur Verfügung stellen können, das möglicherweise ein paar zusätzliche Fehler findet.

Unser Dienstprogramm verwendet das folgende yaml, um die Reihenfolge der Anforderungen zu beschreiben:

Bild

Geschweifte Klammern kennzeichnen Variablen, die beim Testen ersetzt werden. Die Adressvariable wird als CLI-Parameter übergeben, und random generiert eine beliebige Zeichenfolge. Am interessantesten ist hier das Feld response-to-var: Es enthält eine Variable, in die json mit der Serverantwort geschrieben wird. Daher können Sie in der letzten Zeile die ID des erstellten Objekts mit task.id abrufen.

Pain 2. API ist nicht konsistent


Was ist Konsistenz? Wir werden keine formale Definition einführen, aber vereinfachend ist dies interne Konsistenz. Im ersten Projekt musste Vasya beispielsweise Daten zu Berichten in HighLoad aggregieren, und die API bietet eine Datenfilterung nach Jahr. Nachdem das Projekt fast abgeschlossen war, kam Manager Kolya nach Vasya mit der Bitte, Statistiken zu Sprechern in die Analyse aufzunehmen und eine neue Methode „GET-Sprecher“ auch mit Filterung nach Jahr zu erstellen. Infolgedessen vervollständigt Vasya den Code in ein paar Stunden, aber während des Testprozesses stellt sich heraus, dass die Methode nicht funktioniert. Der Grund ist, dass in einem Fall "Jahr" eine Zahl ist, in einem anderen eine Zeichenfolge. Dies ist jedoch auf den ersten Blick nicht ersichtlich und erfordert ständige Sorgfalt bei der Arbeit mit der API. API-Persistenz liegt vor, wenn keine übermäßige Sorgfalt erforderlich ist.

Es gibt viele Beispiele für Inkonsistenzen:

  1. Verwendung verschiedener Formate der gleichen Daten. Zum Beispiel Zeitformat, Art der Kennung (Nummer oder Zeichenfolge UUID),
  2. Anwenden einer anderen Syntax zum Filtern oder Paginieren,
  3. verschiedene Berechtigungsschemata für Dienste. Dabei geht es nicht nur um die Unterschiede zwischen den Programmierern, sondern auch um Tests, die verschiedene Schemata unterstützen müssen.


Behandlung :

  • Überprüfung der Architektur. Wenn es einen Tyrannenarchitekten gibt, wird er (in Abwesenheit von Schizophrenie) für Konsistenz sorgen. Nebenwirkungen: Busfaktor und Tyrannei :)
  • Erstellen der Richtlinien-API. Dies ist ein einzelner Standard, der entwickelt (oder fertiggestellt) werden muss, aber das Wichtigste ist, ihn umzusetzen. Dies erfordert Propaganda, einen Stab und eine Karotte.
  • Implementierung von statischen Prüfungen zur Einhaltung der Annotation API Guideline (lesen Sie dazu hier ).

Bild
Beispiel - Statische Prüflinge

Jedes Unternehmen trifft seine eigene Auswahl der zu verwendenden Richtlinie. Und wahrscheinlich gibt es keinen universellen Ansatz, was sein sollte und was nicht. Denn je mehr Bestimmungen in der Norm enthalten sind, desto strenger müssen Sie kontrollieren und desto mehr schränken Sie die Freiheit der Kreativität ein. Und am wichtigsten ist, dass nur wenige Leute ein Dokument mit „nur 100 Seiten“ bis zum Ende lesen.

In unserem Unternehmen haben wir folgende Punkte in die Richtlinie aufgenommen:

Bild
Weitere gute Beispiele für Richtlinien finden Sie bei Microsoft , PayPal und Google .

Pain 3. API nicht dokumentiert


Das Vorhandensein von Anmerkungen ist eine notwendige, aber nicht ausreichende Bedingung für die einfache Arbeit mit der API. Sie können eine Anmerkung schreiben, damit sie nicht ihr volles Potenzial entfaltet. Dies passiert, wenn:

  1. nicht genügend Beschreibungen (für Parameter, Überschriften, Fehler usw.);
  2. Es gibt nicht genügend Anwendungsbeispiele, da das Beispiel nicht nur zur Verbesserung der Dokumentation (mehr Kontext für den Entwickler und die Möglichkeit, direkt über das Portal mit der API zu spielen), sondern auch zum Testen (als Ausgangspunkt für das Fuzzing) verwendet werden kann.
  3. Es gibt undokumentierte Funktionen.

Dies ist in der Regel der Fall, wenn Entwickler nicht genau wissen, warum die erforderlichen Anmerkungen erforderlich sind, wenn keine Kommunikation zwischen technischen Redakteuren und Programmierern besteht und niemand herausgefunden hat, wie viel das Unternehmen mit unzureichender Dokumentation kostet. Und wenn sie zum Programmierer kämen und nach jeder Bitte um Unterstützung abriefen, würden alle Anmerkungen sehr schnell ausgefüllt.

Behandlung:

  • Verfügbarkeit von API-Referenzgenerierungstools für den Programmierer. Wenn der Entwickler sieht, wie die Beschreibung seiner API für Kollegen und Benutzer aussieht, wird er versuchen, die Annotation zu verbessern. Nebenwirkungen: Die Konfiguration dieser Tools erfordert zusätzliche manuelle Arbeit.
  • Einrichten der Interaktion zwischen allen Beteiligten : Programmierern, Evangelisten, Hilfspersonal. Nebenwirkungen: Jedermann treffen, Prozesse verkomplizieren.
  • Verwenden von Tests basierend auf API-Annotation . Implementierung der obigen statischen Prüfungen in CI-Repositorys mit Anmerkungen.

In Acronis wird eine Annotation-API basierend auf Annotationen mit SDK-Clients und Try-It-Abschnitten generiert. Zusammen mit Codebeispielen und Beschreibungen von Anwendungsfällen bilden sie eine Reihe notwendiger und praktischer Add-Ons für Programmierer. Besuchen Sie unser Portal unter developer.acronis.com

Bild

Ich muss sagen, dass es eine ganze Klasse von Tools zum Generieren der API-Referenz gibt. Einige Unternehmen entwickeln solche Tools selbst für ihre eigenen Bedürfnisse. Andere verwenden relativ einfache und kostenlose Tools wie den Swagger Editor . Nach langen (wirklich langen) Recherchen haben wir uns bei Acronis für Apimatic.io entschieden und es REST United, Mulesoft AnyPoint und anderen vorgezogen.

Pain 4. Probleme mit der Abwärtskompatibilität


Die Abwärtskompatibilität kann durch Kleinigkeiten beeinträchtigt werden. Zum Beispiel schreibt der Programmierer Vasya das Wort Kompatibilität jedes Mal mit einem Tippfehler: Kompatibilität. Dieser Tippfehler ist im Code, in den Kommentaren und in einem Abfrageparameter zu finden. Nachdem Vasya einen Fehler bemerkt hat, ersetzt er dieses Wort während des gesamten Projekts und sendet die Änderungen ohne hinzuschauen an die Produktion. Natürlich wird die Abwärtskompatibilität beeinträchtigt und der Dienst fällt für einige Stunden aus.

Warum können solche Ereignisse überhaupt auftreten? Der Hauptgrund ist ein Missverständnis des API-Lebenszyklus, das sich in fehlerhaften Integrationen, unvorhersehbaren EOL-Richtlinien (End Of Life) und undurchsichtigen API-Releases äußern kann.

Behandlung:

  • Überprüfung der Architektur. Wie immer kann die feste Hand eines Architekten die Abwärtskompatibilität verhindern. Die Hauptaufgabe besteht jedoch darin, die Kosten für die Unterstützung mehrerer Versionen zu erläutern und nach Optionen für Änderungen zu suchen, ohne die vorhandene API zu beschädigen.
  • Abwärtskompatibilitätsprüfung. Wenn die API-Anmerkung eine aktuelle Beschreibung enthält, können Verstöße gegen die Abwärtskompatibilität in der CI-Phase überprüft werden.
  • Rechtzeitige Aktualisierung der Dokumentation. Die API-Referenz und die API-Beschreibung müssen zur gleichen Zeit aktualisiert werden, zu der sich der Servicecode ändert. Dazu können Sie mindestens standardisierte Checklisten starten, Benachrichtigungen für Änderungen einrichten, Superfähigkeiten trainieren, um alles aus allem zu generieren ... Wichtig! Die Dokumentationsabteilung sollte über alle geplanten Änderungen informiert sein, damit sie die Möglichkeit hat, Ressourcen für die Aktualisierung der Dokumentation und das Schreiben von Upgrade-Handbüchern zu planen. Das getestete und verifizierte Upgrade-Handbuch ist ein trauriges Attribut für alle Umbenennungen, die Sie in der API gestartet haben.

Änderungsmanagement


Die Regeln, die die mit dem API-Lebenszyklus verbundenen Aktivitäten beschreiben, werden als Änderungsverwaltungsrichtlinien bezeichnet.

Bild

Wenn Sie zwei Versionen der "aktuellen" und "neuen" Annotationen haben, ist die Abwärtskompatibilitätsprüfung technisch einfach: Analysieren Sie einfach beide Annotationen und prüfen Sie, ob die erforderlichen Felder vorhanden sind

Bild

Wir haben ein spezielles Tool geschrieben, mit dem Sie alle für die Abwärtskompatibilität in CI wichtigen Parameter vergleichen können. Wenn Sie beispielsweise den Antworttext in der GET / healthcheck-Anforderung ändern, wird eine Meldung ähnlich der folgenden angezeigt:

Bild

Fazit


Jeder Architekt träumt davon, API-Probleme loszuwerden. Jeder Manager träumt davon, nichts über API-Probleme zu wissen. :). Es gibt viele Medikamente, aber jedes hat seinen eigenen Preis und seine Nebenwirkungen. Wir haben unsere Behandlungsoptionen für die einfachsten Kinderkrankheiten mit der API geteilt, und dann treten schwerwiegendere Probleme auf. Schlussfolgerungen aus unserem Artikel „Kapitäne“: API-Probleme beginnen mit dem Kopf und das Unterrichten der Menschen in bewährten Praktiken ist die Hauptgarantie für den Erfolg. Alles andere ist nur eine Frage der Technologie. Und vor welchen Problemen standen Sie und welche Mittel zur Lösung haben Sie in Ihrer Organisation gewählt?

Bild
Medikamente gegen die schlechte API.

Wir freuen uns über alle Gedanken, Bewertungen, Kommentare, Meinungen und Fragen!

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


All Articles