Laden...

Wie kann ich in einer Microservice-Struktur aufeinanderfolgende Abläufe failsafe aufsetzen?

Erstellt von emuuu vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.090 Views
emuuu Themenstarter:in
286 Beiträge seit 2011
vor 4 Jahren
Wie kann ich in einer Microservice-Struktur aufeinanderfolgende Abläufe failsafe aufsetzen?

Guten Tag zusammen,

ich habe mal eine Frage wie ich in einer Microservice-Struktur mehrere aufeinanderfolgende Abläufe failsafe aufsetzen kann.

Wenn ich mir einen monolitischen Service, der mit einer Datenbank läuft vorstelle, starte ich eine Transaction und führe meine drei DB-Zugriffe aus: SELECT A, INSERT B, UPDATE C.

Wenn jetzt C aus irgend einem Grund scheitert, habe ich in B eine Entity die da nicht hingehört, weil der ganze Request gescheitert ist und der B nicht in C referenziert wurde.
Im o.g. Beispiel würde ich ein Rollback für die Transaction durchführen und das Thema ist gegessen.

Im Microservice-Ansatz sind A, B & C eigene Services mit eigenen DBs:
Gibt es hierfür einen ähnlich einfachen Ansatz wie Transactions oder bleibt mir nichts anderes als im API-Gateway, dass die Microservices aufruft selber dafür zu sorgen, dass aufgeräumt wird (z.B: catch Exception -> DELETE B -> was mache ich wenn hier auch ein Fehler auftritt weil die DB gerade nen Problem hat)?

Beste Grüße
emuuu

2+2=5( (für extrem große Werte von 2)

16.807 Beiträge seit 2008
vor 4 Jahren

Prinzipiell verfolgt man bei Microservices in den aller meisten Fällen das Prinzip von Event Sourcing - und verfolgt daher meistens Eventual Consistency.
Der Pattern dazu nennt sich Saga (Entwurfsmuster).

Die Alternative nennt sich Multi Phase Commit (oder auch Two Phase Commit).
Hier gibt es eine zusätziche Schicht (Coordinator genannt), der die einzelnen Steps der Transaction ausführt und überwacht.

Letzteres kenne ich persönlich nur aus der Theorie; noch nie wirklich gesehen oder angewendet.

emuuu Themenstarter:in
286 Beiträge seit 2011
vor 4 Jahren

Der Pattern dazu nennt sich
>
.

Super danke. Das entspricht ja in etwa meinem "selber dafür sorgen, dass aufgeräumt wird".

Wäre das im Code eine korrekt Umsetzung:


public aync Task DoStuff()
{
var compensationTasks = new List<Task>();

try
{

var resultFromA = await _dataService.CallServiceA();
compensationTasks.Add(CompensateServiceA());

var resultFromB = await _dataService.CallServiceB(resultFromA);
compensationTasks.Add(CompensateServiceB(resultFromB));


var resultFromC = await _dataService.CallServiceC(resultFromA, resultFromB);
compensationTasks.Add(CompensateServiceC());

}
catch (Exception)
{
Task.WaitAll(compensationTasks.ToArray());
}

}

Würde das aber nicht die Komplexität um einen nicht unerheblichen Faktor nach oben schrauben?

2+2=5( (für extrem große Werte von 2)

16.807 Beiträge seit 2008
vor 4 Jahren

Dein Code ist ganz ganz ganz weit weg von SAGA oder Event Sourcing.
Bei Event Sourcing gibt es keine Direct Calls. Hier arbeitet man mit Events.

Das heisst man hätte pro Business Case entsprechend einen Topic, auf den dann zB. eine Order abgesetzt werden soll.
Klappt das nicht, gibt es einen entsprechenden Error Topic / eine Error Message, auf die dann wiederum jemand anderes hören kann, um eine Stornierung zu triggern.

Was Du da im Code hast ist weit weit weg von irgendwelchen Event-Ideen; das ist eher Multi Phase Commit.

Aber ja, wenn Du alles von einem Service aus koordinierst und auch noch behandeln musst, dann ist das eine sehr hohe Komplexität.
Microservices sind aber nicht unbedingt da, nur alles simpel zu machen - sondern vor allem um die Abhängigkeiten zu lösen und skalieren zu können.
Die wenigsten Umgebungen brauchen aber "echte" Microservices wirklich. Gibt auch viel Bullshit-Clickbait-Videos derzeit leider dazu.