Another Microservice Desaster
Find the English version below
Hi ,
Microservice Architektur
Dieses Buzzword, ist für mich inzwischen ein Trigger geworden. Darüber habe ich schon oft geschrieben.
Anfang des Jahres trendete mein Artikel Microservices are a Big Ball of Mud auf Hacker News
In den 343 Kommentaren zu meinem Artikel kann man gut sehen, wie sehr das Thema die Gemüter erhitzt 😉 Natürlich ist der rationale Blick darauf ein anderer, als ich in dem Artikel dargestellt habe. Es kommt IMMER auf den Kontext an. AppContinuum ist ein hervorragendes Paper zu einem reflektierten Blick auf die Thematik.
Aber in diesem Newsletter soll es wieder darum gehen, wie schnell man sich massive Probleme einhandelt, wenn man eine MicroService Architektur baut
Vor einer Woche berichtete ich wie ein Release bei einem Kunden schief ging. Inzwischen haben wir die Ursache verstanden und gefixt. Wir mussten 1800 Zeilen Code anpassen. Wow.
Wir konnten nicht mehr als 2 Request pro Sekunde verarbeiten. Dann lief unser Connection Pool über. Und wir haben die Ursache rasch erkannt. Während wir die Datenbankverbindung offen hielten wurden mehrere Remote Procedure Calls (RPC) ausgeführt. Diese dauerten einfach zu lange. Die Connection musste die gesamte Zeit offen gehalten werden und der Pool war schneller leer als du bis Drei zählen konntest.
Jetzt sagst du vielleicht: "Na klar. Das ist ja offensichtlich. Mach die calls halt außerhalb der Connection"
Ja. Das stimmt. Die Lösung klingt so simpel. Aber wie immer steckt der Teufel im Detail.
Unsere Connection Strategie ist simpel
Wir öffnen eine Connection, wenn ein neuer Request reinkommt. Machen einen Rollback, wenn eine Exception geschmissen wird. Oder committen, wenn wir mit der Verarbeitung fertig sind. Das Ganze ist schön gekapselt in einem Filter. In Spring nennt sich diese Strategie "Open Session in View" - dazu habe ich erst neulich einen Artikel geschrieben.
Die Strategie ist simpel und sicher. Jede Änderung an unserer Datenbank ist atomar. Wir können keine Inkonsistenzen erzeugen. Das ist gut. Aber in einer Microservice Architektur, die eigentlich ein verteilter Monolith ist, tötet sie jedoch. Denn du musst ja RPC calls zu deinen services in deiner Domänenlogik machen, um an die notwendigen Informationen der anderen Services zu kommen.
Jetzt kann man natürlich sagen: "Aber hey, wenn du das machen musst, dann hast du deine Services wahrscheinlich falsch geschnitten. Das sollte die Ausnahme sein."
Ja. Stimmt. In der Praxis sehe ich allerdings haufenweise Systeme, in denen unter dem Deckmantel einer Microservice Architektur ein verteilter Monolith gebaut wurde. Es ist einfach zu schwer die Services richtig zu schneiden. Leider erlebe ich zu oft, dass ein Team entscheidet mehrere Services zu entwickeln. Das ist meistens der Anfang vom Ende.
Stell dir folgende Frage
Kann (und sollte) mein Service von einem unabhängigen Team vollständig betreut werden? Nein? Dann baust du wahrscheinlich einen verteilten Monolithen.
Es hat mich also wieder getroffen. Was Anfangs gut gemeint ist, endet in einer großen Komplexität und in schmerzhaften Problemen. Es ist nur eines von vielen Beispielen, der letzten Jahre. Und es wird nicht das Letzte sein.
Rule the Backend,
~ Marcus
Hi ,
Microservice Architecture
This buzzword has become a trigger for me. I have written about it often.
Earlier this year, my article Microservices are a Big Ball of Mud trended on Hacker News
The 343 comments on my article clearly show how heated this topic can be 😉 Of course, the rational view on it is different from what I presented in that article. It ALWAYS depends on the context. AppContinuum is an excellent paper offering a reflective view on the subject.
But in this newsletter, we will again address how quickly massive problems can arise when building a MicroService Architecture
A week ago, I reported how a release at a client went wrong. We have now understood and fixed the cause. We had to adjust 1800 lines of code. Wow.
We could not process more than 2 requests per second. Then our connection pool overflowed. And we quickly identified the cause. While holding the database connection open, several Remote Procedure Calls (RPC) were executed. They just took too long. The connection had to be kept open the entire time, and the pool was depleted faster than you could count to three.
You might now say: "Well, obviously. Just make the calls outside of the Connection"
Yes. That's correct. The solution sounds so simple. But, as always, the devil is in the detail.
Our Connection Strategy is Simple
We open a connection when a new request comes in. We roll back if an exception is thrown. Or we commit when we're done processing. All of this is nicely encapsulated in a filter. In Spring, this strategy is called "Open Session in View" - I recently wrote an article about this.
The strategy is simple and safe. Every change to our database is atomic. We can't create inconsistencies. That's good. But in a Microservice Architecture, which is actually a distributed monolith, it kills us. Because you have to make RPC calls to your services in your domain logic to get the necessary information from the other services.
Now, of course, one might say: "But hey, if you have to do that, you've probably cut your services wrong. That should be the exception."
Yes. True. In practice, however, I see plenty of systems where, under the guise of a Microservice Architecture, a distributed monolith has been built. It's just too hard to cut the services correctly. Unfortunately, I too often experience a team deciding to develop several services. That is usually the beginning of the end.
Ask Yourself the Following Question
Can (and should) my service be fully maintained by an independent team? No? Then you are probably building a distributed monolith.
So it hit me again. What starts with good intentions ends in great complexity and painful problems. It's just one of many examples from recent years. And it won't be the last.
Rule the Backend,
~ Marcus