JavaRush /Java-Blog /Random-DE /Ein Leitfaden für Java-Microservices. Teil 3: Allgemeine ...

Ein Leitfaden für Java-Microservices. Teil 3: Allgemeine Fragen

Veröffentlicht in der Gruppe Random-DE
Übersetzung und Anpassung von Java Microservices: Ein praktischer Leitfaden . Vorherige Teile des Leitfadens: Schauen wir uns die inhärenten Probleme von Microservices in Java an, angefangen bei abstrakten Dingen bis hin zu konkreten Bibliotheken. Ein Leitfaden für Java-Microservices.  Teil 3: Allgemeine Fragen - 1

Wie macht man einen Java-Microservice widerstandsfähig?

Denken Sie daran, dass Sie beim Erstellen von Microservices im Wesentlichen JVM-Methodenaufrufe gegen synchrone HTTP-Aufrufe oder asynchrone Nachrichtenübermittlung eintauschen. Während ein Methodenaufruf größtenteils garantiert abgeschlossen wird (mit Ausnahme eines unerwarteten Herunterfahrens der JVM), ist ein Netzwerkaufruf standardmäßig unzuverlässig. Es kann funktionieren, aber aus verschiedenen Gründen kann es auch nicht funktionieren: Das Netzwerk ist überlastet, eine neue Firewall-Regel wurde implementiert und so weiter. Um zu sehen, welchen Unterschied dies macht, werfen wir einen Blick auf das BillingService-Beispiel.

HTTP/REST-Resilienzmuster

Nehmen wir an, Kunden können E-Books auf der Website Ihres Unternehmens kaufen. Zu diesem Zweck haben Sie gerade einen Abrechnungs-Microservice implementiert, der Ihren Online-Shop anrufen kann, um tatsächliche PDF-Rechnungen zu erstellen. Vorerst führen wir diesen Aufruf synchron über HTTP durch (obwohl es sinnvoller ist, diesen Dienst asynchron aufzurufen, da die PDF-Erzeugung aus Sicht des Benutzers nicht sofort erfolgen muss. Im nächsten Beispiel verwenden wir dasselbe Beispiel Abschnitt und sehen Sie sich die Unterschiede an).
@Service
class BillingService {

    @Autowired
    private HttpClient client;

     public void bill(User user, Plan plan) {
        Invoice invoice = createInvoice(user, plan);
        httpClient.send(invoiceRequest(user.getEmail(), invoice), responseHandler());
        // ...
    }
}
Zusammenfassend sind hier drei mögliche Ergebnisse dieses HTTP-Aufrufs.
  • OK: Der Anruf wurde durchgeführt, das Konto wurde erfolgreich erstellt.
  • VERZÖGERUNG: Der Anruf wurde durchgestellt, aber es dauerte zu lange, bis er abgeschlossen war.
  • FEHLER. Der Anruf ist fehlgeschlagen, Sie haben möglicherweise eine inkompatible Anfrage gesendet oder das System funktioniert möglicherweise nicht.
Von jedem Programm wird erwartet, dass es mit Fehlersituationen umgeht, nicht nur mit erfolgreichen. Gleiches gilt für Microservices. Auch wenn Sie zusätzliche Anstrengungen unternehmen müssen, um sicherzustellen, dass alle bereitgestellten Versionen der API kompatibel sind, sobald Sie mit der Bereitstellung und Veröffentlichung einzelner Microservices beginnen. Ein Leitfaden für Java-Microservices.  Teil 3: Allgemeine Fragen - 2Ein interessanter Fall ist der Fall der Verzögerung. Beispielsweise ist die Microservice-Festplatte des Antwortenden voll und die Antwort dauert statt 50 ms 10 Sekunden. Noch interessanter wird es, wenn eine bestimmte Auslastung auftritt, bei der sich die Nichtreaktion Ihres BillingService auf Ihr System auswirkt. Stellen Sie sich als anschauliches Beispiel eine Küche vor, die langsam einen „Block“ aller Restaurantkellner in Betrieb nimmt. Dieser Abschnitt kann natürlich keinen erschöpfenden Überblick über das Thema Microservice-Resilienz bieten, aber er soll Entwickler daran erinnern, dass dies tatsächlich etwas ist, das vor Ihrer ersten Veröffentlichung angegangen und nicht ignoriert werden muss (was erfahrungsgemäß häufiger vorkommt). nicht). folgt). Eine beliebte Bibliothek, die Ihnen beim Nachdenken über Latenz und Fehlertoleranz hilft, ist Hystrix von Netflix. Nutzen Sie die Dokumentation, um tiefer in das Thema einzutauchen.

Messaging-Resilienzmuster

Schauen wir uns die asynchrone Kommunikation genauer an. Unser BillingService-Programm könnte nun etwa so aussehen, vorausgesetzt, wir verwenden Spring und RabbitMQ für die Nachrichtenübermittlung. Um ein Konto zu erstellen, senden wir nun eine Nachricht an unseren RabbitMQ-Nachrichtenbroker, wo mehrere Arbeiter auf neue Nachrichten warten. Diese Mitarbeiter erstellen PDF-Rechnungen und senden sie an die entsprechenden Benutzer.
@Service
class BillingService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

     public void bill(User user, Plan plan) {
        Invoice invoice = createInvoice(user, plan);
        // преобразует счет, например, в json и использует его Wie тело Mitteilungen
        rabbitTemplate.convertAndSend(exchange, routingkey, invoice);
        // ...
    }
}
Potenzielle Fehler sehen jetzt etwas anders aus, da Sie nicht mehr wie bei einer synchronen HTTP-Verbindung sofort OK- oder FEHLER-Antworten erhalten. Stattdessen könnten drei mögliche Szenarien schiefgehen, die folgende Fragen aufwerfen könnten:
  1. Wurde meine Nachricht vom Mitarbeiter übermittelt und verwendet? Oder ist es verloren? (Der Nutzer erhält keine Rechnung).
  2. Wurde meine Nachricht nur einmal zugestellt? Oder mehr als einmal geliefert und nur einmal bearbeitet? (Der Benutzer erhält mehrere Rechnungen).
  3. Konfiguration: Von „Habe ich die richtigen Routing-Schlüssel/Namen für den Austausch verwendet“ bis „Ist mein Nachrichtenbroker richtig konfiguriert und gewartet oder sind seine Warteschlangen voll?“ (Der Nutzer erhält keine Rechnung).
Eine detaillierte Beschreibung jedes einzelnen asynchronen Microservice-Resilienzmusters würde den Rahmen dieses Leitfadens sprengen. Es gibt jedoch Hinweise in die richtige Richtung. Darüber hinaus werden sie auf Messaging-Technologie angewiesen sein. Beispiele:
  • Wenn Sie JMS-Implementierungen wie ActiveMQ verwenden, können Sie Geschwindigkeit gegen die Garantie von Zweiphasen-Commits (XA) eintauschen.
  • Wenn Sie RabbitMQ verwenden, lesen Sie zuerst dieses Tutorial und denken Sie dann sorgfältig über Bestätigungen, Fehlertoleranz und Nachrichtenzuverlässigkeit im Allgemeinen nach.
  • Vielleicht kennt sich jemand gut mit der Konfiguration von Active- oder RabbitMQ-Servern aus, insbesondere in Kombination mit Clustering und Docker (irgendjemand? ;))

Welches Framework wäre die beste Lösung für Java-Microservices?

Einerseits können Sie eine sehr beliebte Option wie Spring Boot installieren . Es macht das Erstellen von .jar-Dateien sehr einfach, verfügt über einen integrierten Webserver wie Tomcat oder Jetty und kann schnell und überall ausgeführt werden. Ideal zum Erstellen von Microservice-Anwendungen. Kürzlich sind einige spezialisierte Microservice-Frameworks, Kubernetes oder GraalVM , erschienen, die teilweise von reaktiver Programmierung inspiriert sind. Hier sind ein paar weitere interessante Konkurrenten: Quarkus , Micronaut , Vert.x , Helidon . Am Ende müssen Sie selbst entscheiden, aber wir können Ihnen ein paar Empfehlungen geben, die vielleicht nicht ganz Standard sind: Mit Ausnahme von Spring Boot werden alle Microservices-Frameworks in der Regel als unglaublich schnell und mit nahezu sofortigem Start vermarktet , geringer Speicherverbrauch, Skalierbarkeit bis ins Unendliche. Marketingmaterialien enthalten in der Regel beeindruckende Grafiken, die die Plattform neben dem riesigen Spring Boot oder nebeneinander präsentieren. Dies schont theoretisch die Nerven von Entwicklern, die ältere Projekte unterstützen, deren Laden manchmal mehrere Minuten dauert. Oder Entwickler, die in der Cloud arbeiten und innerhalb von 50 ms so viele Mikrocontainer starten/stoppen wollen, wie sie gerade benötigen. Ein Leitfaden für Java-Microservices.  Teil 3: Allgemeine Fragen - 3Das Problem besteht jedoch darin, dass diese (künstlichen) Bare-Metal-Startzeiten und Umschichtungszeiten kaum zum Gesamterfolg des Projekts beitragen. Zumindest beeinflussen sie viel weniger als eine starke Framework-Infrastruktur, eine starke Dokumentation, eine Community und starke Entwicklerfähigkeiten. Daher ist es besser, es so zu betrachten: Wenn bisher:
  • Sie lassen Ihre ORMs ungebremst laufen und generieren Hunderte von Abfragen für einfache Workflows.
  • Sie benötigen endlose Gigabyte, um Ihren mäßig komplexen Monolithen zu betreiben.
  • Sie haben so viel Code und die Komplexität ist so hoch (wir sprechen jetzt nicht von potenziell langsamen Startern wie Hibernate), dass das Laden Ihrer Anwendung mehrere Minuten dauert.
Wenn dies der Fall ist, hat das Hinzufügen zusätzlicher Mycoservice-Probleme (Netzwerkausfallsicherheit, Messaging, DevOps, Infrastruktur) weitaus größere Auswirkungen auf Ihr Projekt als das Laden einer leeren „Hello, World“-Umgebung. Und für Hot-Neubereitstellungen während der Entwicklung stehen Ihnen möglicherweise Lösungen wie JRebel oder DCEVM zur Verfügung . Nehmen wir uns einen Moment Zeit, um Simon Brown noch einmal zu zitieren : „ Wenn Menschen keine (schnellen und effizienten) Monolithen bauen können, wird es ihnen schwer fallen, (schnelle und effiziente) Microservices zu erstellen, unabhängig von der Struktur .“ Wählen Sie Ihre Frameworks also mit Bedacht aus.

Welche Bibliotheken eignen sich am besten für synchrone Java-REST-Aufrufe?

Auf der unteren technischen Seite werden Sie wahrscheinlich mit einer der folgenden HTTP-Client-Bibliotheken enden: Javas nativer HttpClient (seit Java 11), Apaches HttpClient oder OkHttp . Beachten Sie, dass ich hier „wahrscheinlich“ sage, weil es andere Optionen gibt, die von guten alten JAX-RS-Clients bis hin zu modernen WebSocket- Clients reichen . Auf jeden Fall geht der Trend hin zur Generierung eines HTTP-Clients, weg vom selbständigen Hantieren mit HTTP-Aufrufen. Dazu müssen Sie einen Blick auf das OpenFeign- Projekt und seine Dokumentation als Ausgangspunkt für weitere Lektüre werfen.

Was sind die besten Broker für asynchrones Java-Messaging?

Höchstwahrscheinlich werden Sie auf das beliebte ActiveMQ (Classic oder Artemis) , RabbitMQ oder Kafka stoßen .
  • ActiveMQ und RabbitMQ sind traditionelle, vollwertige Nachrichtenbroker. Dabei handelt es sich um das Zusammenspiel eines „intelligenten Brokers“ und „dummer Nutzer“.
  • In der Vergangenheit hatte ActiveMQ den Vorteil eines einfachen Inlinings (zum Testen), das mit RabbitMQ/Docker/TestContainer-Einstellungen abgemildert werden kann.
  • Kafka kann nicht als traditioneller „intelligenter“ Broker bezeichnet werden. Stattdessen handelt es sich um einen relativ „dummen“ Nachrichtenspeicher (Protokolldatei), für dessen Verarbeitung intelligente Verbraucher erforderlich sind.
Um besser zu verstehen, wann man RabbitMQ (oder andere traditionelle Nachrichtenbroker im Allgemeinen) oder Kafka verwenden sollte, werfen Sie einen Blick auf diesen Pivotal-Beitrag als Ausgangspunkt. Versuchen Sie bei der Auswahl eines Messaging-Brokers im Allgemeinen, künstliche Leistungsgründe zu ignorieren. Es gab eine Zeit, in der Teams und Online-Communities ständig darüber stritten, wie schnell RabbitMQ und wie langsam ActiveMQ sei. Jetzt werden die gleichen Argumente in Bezug auf RabbitMQ vorgebracht, man sagt, es arbeite langsam mit 20-30.000 Nachrichten pro Sekunde. Kafka zeichnet 100.000 Nachrichten pro Sekunde auf. Ehrlich gesagt sind solche Vergleiche wie der Vergleich von warm mit weich. Darüber hinaus können die Durchsatzwerte in beiden Fällen im niedrigen bis mittleren Bereich beispielsweise der Alibaba Group liegen. Projekte dieser Größenordnung (Millionen Nachrichten pro Minute) haben Sie in der Realität jedoch wahrscheinlich nicht erlebt. Es gibt sie definitiv und sie würden Probleme haben. Im Gegensatz zu den anderen 99 % der „normalen“ Java-Geschäftsprojekte. Achten Sie also nicht auf Mode und Hype. Wählen Sie mit Bedacht.

Welche Bibliotheken kann ich zum Testen von Microservices verwenden?

Es hängt von Ihrem Stapel ab. Wenn Sie ein Spring-Ökosystem im Einsatz haben, ist es ratsam, die spezifischen Tools des Frameworks zu verwenden . Wenn JavaEE so etwas wie Arquillian ist . Eventuell lohnt sich ein Blick auf Docker und die wirklich gute Testcontainers- Bibliothek , die insbesondere dabei hilft, einfach und schnell eine Oracle-Datenbank für lokale Entwicklungs- oder Integrationstests einzurichten. Für Probetests ganzer HTTP-Server schauen Sie sich Wiremock an . Um asynchrones Messaging zu testen, versuchen Sie, ActiveMQ oder RabbitMQ zu implementieren und dann Tests mit Awaitility DSL zu schreiben . Darüber hinaus kommen alle Ihre üblichen Tools zum Einsatz – Junit , TestNG für AssertJ und Mockito . Bitte beachten Sie, dass dies keine vollständige Liste ist. Wenn Sie Ihr Lieblingstool hier nicht finden, posten Sie es bitte im Kommentarbereich.

Wie aktiviere ich die Protokollierung für alle Java-Microservices?

Die Protokollierung bei Microservices ist ein interessantes und recht komplexes Thema. Anstelle einer Protokolldatei, die Sie mit den Befehlen less oder grep bearbeiten können, verfügen Sie jetzt über n Protokolldateien, und Sie möchten, dass diese nicht zu verstreut sind. Die Merkmale des Protokollierungs-Ökosystems werden in diesem Artikel (auf Englisch) ausführlich beschrieben. Lesen Sie es unbedingt durch und achten Sie auf den Abschnitt „Zentralisierte Protokollierung aus der Perspektive von Microservices“ . In der Praxis werden Sie auf unterschiedliche Ansätze stoßen: Der Systemadministrator schreibt bestimmte Skripte, die Protokolldateien verschiedener Server sammeln, in einer einzigen Protokolldatei zusammenführen und auf FTP-Servern zum Herunterladen bereitstellen. Ausführen von cat/grep/unig/sort-Kombinationen in parallelen SSH-Sitzungen. Genau das macht Amazon AWS, und Sie können es Ihrem Vorgesetzten mitteilen. Verwenden Sie ein Tool wie Graylog oder ELK Stack (Elasticsearch, Logstash, Kibana)

Wie finden meine Microservices einander?

Bisher sind wir davon ausgegangen, dass unsere Microservices voneinander wissen und das entsprechende IPS kennen. Lassen Sie uns über die statische Konfiguration sprechen. Unser Bankmonolith [ip = 192.168.200.1] weiß also, dass er mit dem Risikoserver [ip = 192.168.200.2] kommunizieren muss, der in der Eigenschaftendatei fest codiert ist. Sie können die Dinge jedoch dynamischer gestalten:
  • Verwenden Sie einen cloudbasierten Konfigurationsserver, von dem alle Microservices ihre Konfigurationen abrufen, anstatt application.properties-Dateien auf ihren Microservices bereitzustellen.
  • Da Ihre Dienstinstanzen ihren Standort dynamisch ändern können, lohnt es sich, nach Diensten zu suchen, die wissen, wo sich Ihre Dienste befinden, welche IP-Adressen sie haben und wie sie weitergeleitet werden.
  • Da nun alles dynamisch ist, entstehen neue Probleme, wie zum Beispiel die automatische Wahl eines Leiters: Wer ist der Herr, der bestimmte Aufgaben bearbeitet, um sie beispielsweise nicht zweimal zu bearbeiten? Wer ersetzt einen Anführer, wenn er versagt? Auf welcher Grundlage erfolgt die Ersetzung?
Im Allgemeinen wird dies als Microservice-Orchestrierung bezeichnet und ist ein weiteres bodenloses Thema. Bibliotheken wie Eureka oder Zookeeper versuchen, diese Probleme zu „lösen“, indem sie zeigen, welche Dienste verfügbar sind. Andererseits führen sie zu zusätzlicher Komplexität. Fragen Sie jeden, der ZooKeeper jemals installiert hat.

Wie organisiert man Autorisierung und Authentifizierung mithilfe von Java-Microservices?

Dieses Thema verdient auch eine eigene Geschichte. Auch hier reichen die Optionen von hartcodierter grundlegender HTTPS-Authentifizierung mit benutzerdefinierten Sicherheits-Frameworks bis hin zur Ausführung einer Oauth2-Installation mit einem eigenen Autorisierungsserver.

Wie kann ich sicherstellen, dass alle meine Umgebungen gleich aussehen?

Was für Bereitstellungen ohne Microservice gilt, gilt auch für Bereitstellungen mit einem. Versuchen Sie es mit einer Kombination aus Docker/Testcontainers und Scripting/Ansible.

Keine Frage: kurz zu YAML

Lassen Sie uns für einen Moment von Bibliotheken und verwandten Themen Abstand nehmen und einen kurzen Blick auf Yaml werfen. Dieses Dateiformat wird de facto als Format zum „Schreiben von Konfiguration als Code“ verwendet. Es wird auch von einfachen Tools wie Ansible und Giganten wie Kubernetes verwendet. Um den Schmerz der YAML-Einrückung zu erleben, versuchen Sie, eine einfache Ansible-Datei zu schreiben und sehen Sie, wie viel Sie an der Datei bearbeiten müssen, bevor sie wie erwartet funktioniert. Und das, obwohl das Format von allen wichtigen IDEs unterstützt wird! Kommen Sie danach noch einmal zurück, um diesen Leitfaden zu Ende zu lesen.
Yaml:
  - is:
    - so
    - great

Was ist mit verteilten Transaktionen? Leistungstest? Andere Themen?

Vielleicht eines Tages in zukünftigen Ausgaben des Handbuchs. Im Moment ist das alles. Bleib bei uns!

Konzeptionelle Probleme mit Microservices

Neben den spezifischen Problemen von Microservices in Java gibt es beispielsweise noch andere Probleme, die in jedem Microservice-Projekt auftreten. Sie beziehen sich hauptsächlich auf Organisation, Team und Management.

Nichtübereinstimmung zwischen Frontend und Backend

Die Nichtübereinstimmung von Frontend und Backend ist in vielen Microservice-Projekten ein sehr häufiges Problem. Was bedeutet das? Nur dass Web-Interface-Entwickler in den guten alten Monolithen eine bestimmte Quelle zum Abrufen von Daten hatten. In Microservice-Projekten haben Frontend-Entwickler plötzlich n Quellen, aus denen sie Daten beziehen können. Stellen Sie sich vor, Sie erstellen eine Art IoT-Microservices-Projekt (Internet of Things) in Java. Nehmen wir an, Sie verwalten geodätische Maschinen und Industrieöfen in ganz Europa. Und diese Öfen senden Ihnen regelmäßig Updates mit ihren Temperaturen und dergleichen. Früher oder später möchten Sie möglicherweise Öfen in der Admin-Benutzeroberfläche finden, möglicherweise mithilfe der Microservices „Ofensuche“. Abhängig davon, wie strikt Ihre Back-End-Kollegen die domänengesteuerten Design- oder Microservice-Gesetze anwenden, gibt der Microservice „Find Oven“ möglicherweise nur Ofen-IDs und keine anderen Daten wie Typ, Modell oder Standort zurück. Dazu müssen Frontend-Entwickler einen oder mehrere zusätzliche Aufrufe (abhängig von der Paging-Implementierung) im Microservice „Get Oven Data“ mit den IDs durchführen, die sie vom ersten Microservice erhalten haben. Ein Leitfaden für Java-Microservices.  Teil 3: Allgemeine Fragen - 4Und obwohl dies nur ein einfaches Beispiel ist, wenn auch einem echten (!) Projekt entnommen, zeigt es doch folgendes Problem: Supermärkte sind extrem beliebt geworden. Denn mit ihnen müssen Sie nicht an 10 verschiedene Orte gehen, um Gemüse, Limonade, Tiefkühlpizza und Toilettenpapier zu kaufen. Stattdessen gehen Sie an einen Ort. Das ist einfacher und schneller. Das Gleiche gilt für Frontend- und Microservice-Entwickler.

Erwartungen des Managements

Das Management hat den falschen Eindruck, dass es nun unendlich viele Entwickler für ein (übergreifendes) Projekt einstellen muss, da die Entwickler nun völlig unabhängig voneinander arbeiten können, jeder an seinem eigenen Microservice. Lediglich ganz am Ende (kurz vor dem Start) ist noch ein wenig Integrationsarbeit nötig. Ein Leitfaden für Java-Microservices.  Teil 3: Allgemeine Fragen – 5Tatsächlich ist dieser Ansatz äußerst problematisch. In den folgenden Abschnitten werden wir versuchen zu erklären, warum.

„Kleinere Stücke“ sind nicht gleich „bessere Stücke“

Es wäre ein großer Fehler anzunehmen, dass in 20 Teile unterteilter Code notwendigerweise eine höhere Qualität aufweist als ein ganzes Stück. Selbst wenn wir Qualität aus rein technischer Sicht betrachten, führen unsere einzelnen Dienste möglicherweise immer noch 400 Hibernate-Abfragen aus, um einen Benutzer aus der Datenbank auszuwählen, und durchlaufen dabei Schichten nicht unterstützten Codes. Wir kehren noch einmal zum Zitat von Simon Brown zurück: Wenn es nicht gelingt, Monolithen richtig zu bauen, wird es schwierig, richtige Microservices zu bauen. Es ist oft extrem spät, über Fehlertoleranz in Microservice-Projekten zu sprechen. So sehr, dass es manchmal beängstigend ist, zu sehen, wie Microservices in realen Projekten funktionieren. Der Grund dafür ist, dass Java-Entwickler nicht immer bereit sind, Fehlertoleranz, Netzwerke und andere verwandte Themen auf dem richtigen Niveau zu studieren. Die „Teile“ selbst sind kleiner, die „technischen Teile“ jedoch größer. Stellen Sie sich vor, Ihr Microservices-Team wird gebeten, einen technischen Microservice für die Anmeldung bei einem Datenbanksystem zu schreiben, etwa so:
@Controller
class LoginController {
    // ...
    @PostMapping("/login")
    public boolean login(String username, String password) {
        User user = userDao.findByUserName(username);
        if (user == null) {
            // обработка варианта с несуществующим пользователем
            return false;
        }
        if (!user.getPassword().equals(hashed(password))) {
            // обработка неверного пароля
            return false;
        }
        // 'Ю-ху, залогинoderсь!';
        // установите cookies, делайте, что угодно
        return true;
    }
}
Jetzt kommt Ihr Team möglicherweise zu dem Schluss (und überzeugt vielleicht sogar die Geschäftsleute), dass dies alles zu einfach und langweilig ist. Anstatt einen Anmeldedienst zu schreiben, ist es besser, einen wirklich nützlichen UserStateChanged-Mikrodienst ohne echte und greifbare geschäftliche Auswirkungen zu schreiben. Und da einige Leute Java derzeit wie einen Dinosaurier behandeln, schreiben wir unseren UserStateChanged-Microservice im modischen Erlang. Und versuchen wir mal, irgendwo rot-schwarze Bäume zu verwenden, denn Steve Yegge hat geschrieben, dass man sie in- und auswendig kennen muss, um sich bei Google zu bewerben. Aus Sicht der Integration, der Wartung und des Gesamtdesigns ist dies genauso schlimm wie das Schreiben von Spaghetti-Codeschichten in einen einzigen Monolithen. Ein künstliches und gewöhnliches Beispiel? So ist das. Dies kann jedoch in der Realität passieren.

Weniger Teile – weniger Verständnis

Dann stellt sich natürlich die Frage, wie man das System als Ganzes, seine Prozesse und Arbeitsabläufe versteht, aber gleichzeitig sind Sie als Entwickler nur für die Arbeit an Ihrem isolierten Microservice verantwortlich [95: login-101: updateUserProfile]. Es stimmt mit dem vorherigen Absatz überein, aber abhängig von Ihrer Organisation, dem Grad des Vertrauens und der Kommunikation kann dies zu großer Verwirrung, Schulterzucken und Schuldzuweisungen führen, wenn es zu einem versehentlichen Zusammenbruch der Microservice-Kette kommt. Und es gibt niemanden, der die volle Verantwortung für das, was passiert ist, übernehmen würde. Und es geht überhaupt nicht um Unehrlichkeit. Tatsächlich ist es sehr schwierig, verschiedene Teile miteinander zu verbinden und ihren Platz im Gesamtbild des Projekts zu verstehen.

Kommunikation und Service

Der Kommunikations- und Servicegrad variiert stark je nach Unternehmensgröße. Der allgemeine Zusammenhang ist jedoch offensichtlich: Je mehr, desto problematischer.
  • Wer betreibt Microservice Nr. 47?
  • Haben sie gerade eine neue, inkompatible Version eines Microservices bereitgestellt? Wo wurde das dokumentiert?
  • Mit wem muss ich sprechen, um eine neue Funktion anzufordern?
  • Wer wird diesen Mikroservice in Erlang unterstützen, nachdem der einzige, der diese Sprache beherrschte, das Unternehmen verlassen hat?
  • Alle unsere Microservice-Teams arbeiten nicht nur in unterschiedlichen Programmiersprachen, sondern auch in unterschiedlichen Zeitzonen! Wie koordinieren wir das alles richtig?
Ein Leitfaden für Java-Microservices.  Teil 3: Allgemeine Fragen – 6Der Hauptpunkt ist, dass ein vollwertiger Ansatz für Microservices in einem großen, vielleicht sogar internationalen Unternehmen, wie bei DevOps, eine Reihe zusätzlicher Kommunikationsprobleme mit sich bringt. Und darauf muss sich das Unternehmen ernsthaft vorbereiten.

Schlussfolgerungen

Nachdem Sie diesen Artikel gelesen haben, denken Sie vielleicht, dass der Autor ein leidenschaftlicher Gegner von Microservices ist. Das ist nicht ganz richtig – ich versuche im Grunde, Punkte hervorzuheben, denen im hektischen Wettlauf um neue Technologien nur wenige Menschen Aufmerksamkeit schenken.

Microservices oder Monolith?

Ein Extrem ist es, Java-Microservices jederzeit und überall zu nutzen. Das andere entpuppt sich als so etwas wie Hunderte von guten alten Maven-Modulen in einem Monolithen. Ihre Aufgabe ist es, die richtige Balance zu finden. Dies gilt insbesondere für neue Projekte. Nichts hindert Sie daran, einen konservativeren, „monolithischen“ Ansatz zu wählen und weniger gute Maven-Module zu erstellen, anstatt mit zwanzig Cloud-fähigen Microservices zu beginnen.

Microservices erzeugen zusätzliche Komplexität

Denken Sie daran, dass Sie später im Prozess umso mehr Probleme haben werden, je mehr Microservices Sie haben und je weniger leistungsstarke DevOps Sie haben (nein, das Ausführen einiger Ansible-Skripte oder die Bereitstellung auf Heroku zählt nicht!). Selbst das Lesen des Abschnitts dieses Handbuchs, der allgemeine Fragen zu Java-Microservices behandelt, bis zum Ende ist eine ziemlich mühsame Aufgabe. Denken Sie gründlich darüber nach, Lösungen für all diese Infrastrukturprobleme zu implementieren, und Sie werden plötzlich feststellen, dass es nicht mehr nur um Geschäftsprogrammierung geht (wofür Sie bezahlt werden), sondern vielmehr darum, mehr Technologie auf noch mehr Technologie zu installieren. Shiva Prasad Reddy hat es in seinem Blog perfekt auf den Punkt gebracht : „Sie haben keine Ahnung, wie schrecklich es ist, wenn ein Team 70 % der Zeit damit verbringt, sich mit dieser modernen Infrastruktur herumzuschlagen, und nur 30 % der Zeit für die eigentliche Geschäftslogik übrig bleibt.“ „ Shiva Prasad Reddy

Lohnt es sich, Java-Microservices zu erstellen?

Um diese Frage zu beantworten, möchte ich diesen Artikel mit einem sehr frechen, an ein Google-Interview erinnernden Teaser beenden. Wenn Sie die Antwort auf diese Frage aus Erfahrung kennen, auch wenn sie scheinbar nichts mit Microservices zu tun hat, sind Sie möglicherweise bereit für einen Microservices-Ansatz.

Szenario

Stellen Sie sich vor, Sie haben einen Java-Monolithen, der allein auf dem kleinsten dedizierten Hetzner- Server läuft . Das Gleiche gilt für Ihren Datenbankserver, er läuft ebenfalls auf einer ähnlichen Hetzner- Maschine . Nehmen wir außerdem an, dass Ihr Java-Monolith Workflows verarbeiten kann, beispielsweise die Benutzerregistrierung, und Sie nicht Hunderte von Datenbankabfragen pro Workflow erstellen, sondern eine angemessenere Anzahl (<10).

Frage

Wie viele Datenbankverbindungen sollte Ihr Java-Monolith (Verbindungspool) auf Ihrem Datenbankserver öffnen? Warum so? Wie viele gleichzeitig aktive Benutzer kann Ihr Monolith Ihrer Meinung nach (ungefähr) skalieren?

Antwort

Hinterlassen Sie Ihre Antwort auf diese Fragen im Kommentarbereich. Ich freue mich auf alle Antworten. Ein Leitfaden für Java-Microservices.  Teil 3: Allgemeine Fragen – 8Jetzt entscheiden Sie sich. Wenn Sie bis zum Ende lesen, sind wir Ihnen sehr dankbar!
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION