Wie können Microservices geschnitten werden?

Microservices sind ein wirklich guter Architektur-Ansatz. Sie richtig zu schneiden, erscheint allerdings schwierig und wird in der Community ausführlich diskutiert. Dieser Post diskutiert die Möglichkeiten Microservices entlang des Business-Prozesses zu schneiden – wobei ein Business-Prozess-Schritt ein Microservice ist.

The term “Microservice Architecture” has sprung up over the last few years to describe a particular way of designing software applications as suites of independently deployable services.” Martin Fowler, James Lewis 2014 (https://martinfowler.com/articles/microservices.html)

 Offensichtlich entscheidet nicht die Anzahl der Codezeilen oder die Anzahl der Schnittstellen, ob ein Service ein Microservice ist oder nicht. Nein, es ist eine Business-Funktion, die unabhängig deployed und betrieben werden kann. Ich möchte keine kleinen Services, nur weil sie klein sind. I möchte kleine Services haben, weil sie die gesamte Applikation stabiler und performanter machen. OK, alles das klingt sehr verständlich, aber wie bekomme ich denn nun Microservices für eine Applikation – ich spreche ja gar nicht von Legacy-Applikationen.

Offensichtlich macht es keinen Sinn, sie in der gleichen Art und Weise wie unsere guten, alten n-Tier-Applikationen zu schneiden. Wenn wir einen Service für das Benutzer-Interface, die Business-Logik und die Persistenz-Schicht haben, würden diese nicht unabhängig deploybar sein. Natürlich kann ich es technisch erreichen, aber mit jeder neuen Business-Funktion muss ich alle drei Services deployen. In diesem Sinne habe ich keinen Vorteil gegenüber meinen guten, alten Monolithen.

I muss entlang der Business Funktionen schneiden. OK – klingt gut, aber wie kann ich das tun? I möchte es anhand eines Beispiels erläutern. Lass uns annehmen, dass wir einen Ausschreibungsprozess haben, den wir implementieren wollen. Um die Business-Funktionen zu finden, die unabhängig voneinander deploybar sind, sehen wir uns den Business-Prozess an – die Business-Funktionen sollten dann erkennbar sein. Eine erste Skizze könnte wie folgt aussehen:

IMG_0211

  1. Ein Ingenieur erzeugt eine neue Planung, z.B. für ein neues Haus. Die Planung wird als neue Planungsdokumente gespeichert.
  2. Der Ingenieur erzeugt die zugehörigen Zeichnungen und fügt sie zu den Planungsdokumenten hinzu.
  3. Ein potentieller Vertragsnehmer (Contractor) prüft die Planungsdokumente und erstellt ein Gebot basierend darauf.
  4. Der Manager prüft die Gebote und schlägt den Auftrag einem zu (Awarding).

Wie wir sehen können, ist der gezeigte Business-Prozess nicht gut genug, um unsere Microservices darauf basieren zu lassen. Der Vertragsnehmer fällt vom Himmel. Warum sollte er ein Gebot senden? So, wir brauchen als etwas, das die Planungs-Dokumente auf der einenn Seite und eine Liste von potentiellen Vertragsnehmern auf der anderen Seite enthält. Mehr noch, das Business-Objekt „Call of Bids“ muss alle Gebote enthalten, die durch alle eingeladenen Vertragsnehmer abgegeben wurden. Nur in einem solchen Weg ist es möglich, dass die Gebote effizient evaluiert werden können. Unser zweiter Entwurf sieht dann ungefähr so aus:

IMG_0212

  1. Der Ingenieur erzeugt die Planungs-Dokumente einschließlich aller notwendigen Zeichnungen. (Ich bedaure, dass die Zeichnungen nicht so wichtig für unser Modell sind L) Die Planungs-Dokumente bekommen den Status NEW.
  2. Der Ingenieur erzeugt die Ausschreibung, die den Status NEW bekommt und die eine Liste der potentiellen Vertragsnehmer enthält. Lass uns hier annehmen, dass es sich um eine geschlossene Ausschreibung handelt, in der alle potentiellen Vertragsnehmer bekannt sind. Es macht das Beispiel einfacher ohne den Effekt, den ich erläutern möchte zu verschleiern.
  3. Der Vertragsnehmer bekommt die Information, das von ihm erwartet wird, dass er ein Angebot für das Projekt abgibt. Er erzeugt das Gebot und sendet es zurück. Das Gebot bekommt den Status NEW. (Wenigstens in meinem Beispiel. Du magst denken, dass Status-Übergänge von NEW – DRAFT – SENT besser sind. Und ich muss Dir zustimmen, aber bleibe bitte bei mir und meinem Beispiel.)
  4. Wenn alle Gebote abgegeben sind, kann der Manager die Gebote evaluieren. Die Gebote bekommen den Status EVALUATED.
  5. Basieren auf der Evaluation bekommt ein Gebot den Zuschlag durch den Manager. Das Gebot bekommt den Status AWARDED.

Und was hat nun das Beispiel mit Microservices zu tun? Wenn wir Microservices schneiden wollen, wollen wir sie unabhängig deployen. Microservices innerhalb einer Business-Funktion zu schneiden, macht keinen Sinn, weil dann jeder dieser Microservices deployed werden muss, wenn sich die Business-Funktion ändert. Im Sinne eines Design Driven Development, brauchen wir die Grenze der Besorgnis (Border of Concern). Und diese Grenzen begrenzen dann exakt unsere Business-Funktionen.

Die Business-Funktionen können dann durch

  • eine Statusänderung des Haupt-Business-Objekts oder
  • die Änderung der handelnden Rolle

abgegrenzt werden.

Lass mich das in unserem Beispiel erklären. In den Schritten „Erzeuge Planungsdokument (Create Planning Documents)“ und „Erzeuge Ausschreibung (Create Call of Bids)“ ist in beiden Fällen die handelnde Rolle Ingenieur. Aber im ersten Schritt existiert das Haupt-Business-Objekt „Ausschreibung (Call of Bids)“ noch nicht einmal. Es kann hinterfragt werden, ob dieser Schritt überhaupt zum Business-Prozess gehört.  Wie auch immer, der Status der Ausschreibung (Call of Bids) ändert sich von NOT EXISTING zu NEW, welches eine Grenze anzeigt.

Im nächsten Übergang von „Erzeuge Ausschreibung (Create Call of Bids)“ zu „Erzeugt Gebot (Create Bid)“ ändert sich die handelnde Rolle vom Ingenieur zum Vertragsnehmer. Und danach vom Vertragsnehmer zum Manager.

Im letzten Übergang bleibt die handelnde Rolle erhalten, aber der Status ändert sich von evaluiert (EVALUATED) zu vergeben (AWARDED). Der Status kann von einem einzelnen Gebot auf die Ausschreibung übertragen werden.

So, mit dem gezeigten Ansatz haben wir die folgenden Services

  • Erzeuge Planungsdokumente (Create Planning Documents)
  • Erzeuge Ausschreibung (Create Call of Bids)
  • Erzeuge Gebot (Create Bid)
  • Evaluiere Gebote (Evaluate Bids)
  • Zuschlag (Awarding)

Diese Services können gut implementiert und deployed werden, ohne dass sie sich gegenseitig beeinflussen. Natürlich mögen Änderungen notwendig sein, die alle Services betreffen, aber diese sind nach meiner Erfahrung recht selten und müssen ohnehin gründlich geplant werden. Aber sie können Schritt für Schritt implementiert werden und kein Big-Bang ist notwendig.

Hmm, I denke, Du bist nicht zufrieden mit der Lösung. Du hörst Deinen Manger: „Es ist zu teuer. Ich kann doch keine Datenbank für jeden Service zahlen. I kann keine Synergien nutzen. Bist Du verrückt?” Um ehrlich zu sein, ich höre diese Argumente von meinem Manager auch. Du kannst dieses Problem mit unterstützenden Services lösen, die ich in meinem nächsten Blog erläutern möchte.

 

One thought on “Wie können Microservices geschnitten werden?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s