Microservices aus Sicht der Software- und Facharchitektur (Microservices, Teil 3)

Die größte Herausforderung beim Einsatz von Microservices ist es, den richtigen Zuschnitt der Services zu finden. Services müssen kohärent sein. Während der Zuschnitt der Services für technologisch motivierte Services wie Logging oder Drucken noch relativ offensichtlich ist, ist es schwierig, die Fachlichkeit und ihre Abgrenzung (Business Capabilities) von Services zu beschreiben.

Das spektakuläre Buch Domain Driven Design von Evans [Evans] liefert den konzeptionellen Hintergrund, um Domänenmodelle inklusive ihrer Abgrenzungen (boundary context) zu beschreiben. Ein boundary context ist eine natürliche Grenze für einen Microservice. Insbesondere ist ein Microservice exklusiv für die Daten seines Domänenmodells verantwortlich.

Durch die Entkopplung und Verteilung der Microservices wird der richtige Zuschnitt des Microservices zu einer Schlüsselentscheidung, welche über den Erfolg des Microservices entscheidet. Stellt sich heraus, dass der Microservice nicht korrekt definiert ist, ist ein Redesign schwierig. Häufig enden Designfehler darin, diese im public interface trickreich zu überspielen. Das so entstehende public interface wird sehr schnell kompliziert und unverständlich.

Microservices laufen in einzelnen Prozessen. Daher erstrecken sich Transaktionen a priori höchstens auf einen Microservices. Konzepte wie verteilte Transaktionen über Grenzen von Microservices hinweg sind technologisch schwer zu beherrschen. Zudem verletzten sie die Eigenverantwortlichkeit der Microservices. Daher sind sie keine gute Wahl in einer Microservice-Architektur. Transaktionen sind also die untere Grenze für die Verantwortlichkeit eines Microservice.

Was geschieht aber mit Konsistenzbedingungen zwischen den Microservices, welche in einer monolithischen Anwendung durch eine Transaktion über Servicegrenzen hinweg sichergestellt werden? Kurz gesagt: von diesem Gedanken sollte man sich verabschieden. Jeder Microservice ist für die Konsistenz seines Domänenmodells verantwortlich. Abhängigkeiten der Konsistenz zwischen den Domänenmodellen werden nicht explizit sichergestellt (z.B. Orchestrierung), sondern Änderungen an einem Datenmodell werden an andere Microservices propagiert. Diese können darauf durch Anpassungen an ihrem Domänenmodell reagieren. Aus diesem Ansatz ergeben sich zwei Folgerungen:

  • Wenn jeder Microservice für sein Domänenmodell zuständig ist, braucht es keine zentrale Datenbank, sondern jeder Microservice kann seine eigene Datenhaltung besitzen (dezentrale Datenhaltung).
  • Eine Konsistenz über unterschiedliche Domänenmodelle kann nicht zu jedem Zeitpunkt sichergestellt werden. Systeme müssen so ausgelegt sein, dass sie mit diesem neuen Konsistenzbegriff umgehen können (eventually consistent).

Die Diskussion über die Konsistenz über Domänenmodelle hinweg führt zur spannenden Frage des Kommunikationsverfahrens: synchron oder asynchron. Die Benachrichtigung anderer Microservices über Änderungen eines Domänenmodells muss nicht notwendigerweise synchron geschehen, denn eine transaktionale Konsistenz ist – wie oben beschrieben – nicht zu erreichen.

Jede synchrone Kommunikation birgt aber das Risiko, in die Fallen der verteilten Systeme zu geraten. Sender und Empfänger sind zeitlich gekoppelt. Jede fehlgeschlagene synchrone Kommunikation wirkt sich unmittelbar auf das Antwortverhalten des Microservices aus.
Daher ist es vorteilhaft, den synchronen Anteil der verteilten Kommunikation möglichst klein zu halten. Der eigentliche Geschäftsvorfall mit unmittelbarer Rückkopplung zum Nutzer wird in der Regel synchron ausgeführt. Benachrichtigungen an andere Microservices über Datenmodelländerungen werden am besten über asynchrones Message Queuing umgesetzt.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.