Können Sie Deadlock auf Camunda BPM schreiben? ich kann

Bild


Vor einiger Zeit schrieb ich über die erfolgreiche Migration von IBM BPM nach Camunda, und jetzt ist unser Leben voller Glück und angenehmer Eindrücke. Camunda hat uns nicht enttäuscht und wir setzen unsere Freundschaft mit dieser BPM-Engine fort.



Leider kann Camunda unangenehme Überraschungen bereiten, aufgrund derer manchmal nicht die offensichtlichsten Ergebnisse erzielt werden. In diesem Artikel wird ein Fall betrachtet, der sich trotz seiner Einfachheit als interessant und etwas komplexer herausstellte, als es auf den ersten Blick schien.



Wir trainieren an Katzen



Betrachten Sie zur Beschreibung des Problems ein synthetisches Beispiel. Nehmen wir an, wir haben beschlossen, unseren Kundenstamm zu erweitern und müssen Katzen und Katzen bedienen. Jeder potenzielle Kunde sollte überprüft werden und möglicherweise sofort etwas anbieten.



Wir werden die Zuverlässigkeit des Kandidaten und die möglichen Dienstleistungen prüfen, die wir ihm anbieten können. Due Diligence und mögliche Dienstleistungen stehen in keiner Beziehung zueinander - diese Maßnahmen können parallel durchgeführt werden. In einem BPMN-Diagramm sieht es schematisch folgendermaßen aus:





Diagramm 1. Schematischer Prozess der flauschigen Wartung



Das Diagramm zeigt schematisch die Hauptschritte: Gabeln und Sammeln (Verbinden) von Gateways.





Dieses Symbol steht für ein paralleles Gateway. Paralleles Gateway ist das einfachste Gateway zum Erstellen eines parallelen Teils eines Prozesses.



Es gibt zwei Arten von parallelen Gateways:



  • fork - erstellt eine separate Ausführung für jeden Zweig;
  • join - Wartet, bis alle eingehenden Ausführungen abgeschlossen sind.


Ausführung - Stellen Sie einen 'Ausführungspfad' in einer Prozessinstanz dar (aus der Dokumentation). Das heißt, es ist ein Prozessausführungsthread.



Lassen Sie uns nun die Aufgabe etwas komplizieren. Wir prüfen und suchen auf folgende Weise nach Diensten: Zuerst überprüfen wir den Status des Kunden, dann prüfen wir, welche Dienste zu ihm passen können, und führen eine Vorverarbeitung durch. Darüber hinaus können mehrere Dienste gleichzeitig für einen Kunden geeignet sein, sodass wir dem Kunden alle anbieten können müssen.



Da wir mit pelzigen Kunden zusammenarbeiten, sind die Dienstleistungen angemessen: Baldrian, Klauenschwader, Meisterkissen und andere nützliche Dinge.





Diagramm 2. Verfeinertes, flauschiges Kundendienstdiagramm Die



neue Version des Prozesses sieht folgendermaßen aus. Der Prozess entspricht der Überprüfung der Zuverlässigkeit und der Suche nach möglichen Vorschlägen. Die Suche ist ebenfalls parallelisiert. In diesem Fall werden die Zweige ausgeführt, für die die entsprechenden Bedingungen erfüllt sind.



Für die Parallelisierung mit Bedingungen wird das Inclusive Gateway verwendet, das durch das folgende Symbol angezeigt wird:





Inclusive Gateway ist ein paralleles Gateway mit Verzweigungsbedingungen. Die Zweige, für die die Bedingungen erfüllt sind, werden ausgeführt.



Es gibt zwei Arten von Gateways:



  • Fork - Für jeden Zweig mit der erfüllten Bedingung wird eine Ausführung erstellt, die parallel zur Ausführung im Parallel Gateway ausgeführt wird.
  • join wartet im Gegensatz zu Parallel Gateway nicht auf Ausführungen für alle Zweige, sondern nur auf diejenigen, für die die Bedingung erfüllt ist.


Es kann vorkommen, dass die durchgeführten Überprüfungen nicht ausreichen und der Client erneut überprüft werden muss. Fügen Sie dazu am Ende aller Überprüfungen eine Bedingung hinzu, die zur erneuten Überprüfung an den Anfang gesendet werden kann:





Abbildung 3. Die endgültige Version des Prozesses, die funktionieren sollte



Es stellte sich als umständlich heraus, aber der Prozess löst das Problem.



Was? Was ist passiert?



Hier beginnen seltsame Dinge zu passieren. Der Zuverlässigkeitsüberprüfungszweig erfüllt und erreicht das sammelnde parallele Gateway. Bisher läuft alles gut.



Der zweite Zweig prüft den Materialzustand und abhängig von den Ergebnissen werden die entsprechenden Aufgaben ausgeführt. Als nächstes stoppt der Prozess am Gateway und sammelt Inclusive Gateway und bewegt sich nicht weiter. Wenn Sie sich das Coockpit (Admin-Panel der Kamunda) ansehen, hängen die Ausführungen am gesammelten Inclusive Gateway und Parallel Gateway.





Abbildung 4. Hängender Wartungsprozess



. Fertig. Wir können sagen, dass wir auf Camunda einen Stillstand haben. In diesem Fall steht es nicht in direktem Zusammenhang mit Deadlocks aus der Theorie der parallelen Programmierung und Deadlocks.



Auf der Suche nach ̶̶̶̶̶̶̶̶̶̶̶̶ Antwort



Da ich nicht genügend Verständnis dafür hatte, was passiert ist und warum der Prozess gestoppt wurde, musste ich das Problem empirisch lösen.



Möglicherweise benötigen Sie einen Standardzweig für das Inclusive Gateway, und ohne diesen kann der Prozess nicht normal ausgeführt werden?



Seltsam natürlich, aber versuchen Sie, einen Standardzweig hinzuzufügen. Das Vorhandensein eines Standardzweigs ist eine gute Vorgehensweise, da andernfalls möglicherweise keine einzige Bedingung erfüllt ist und wir dann eine Fehlermeldung erhalten.





Abbildung 5. Serviceprozess mit Standardzweig



Starten Sie und erhalten Sie das gleiche Ergebnis - der Prozess bleibt beim Sammeln von Inclusive Gateway hängen.



Als nächstes folgt die Aufzählung aller Arten von Parametern, das Lesen der Dokumentation, und dies dauert einen halben Tag. Bei einem weiteren Versuch besteht der Prozess unerwartet die unglückliche Umfrage. Der untere Zweig mit Inclusive Gateway funktionierte in einer Situation, in der während des Such- und Debugging-Vorgangs der obere Zweig mit einer Client-Zuverlässigkeitsprüfung gelöscht wurde. Das heißt, wenn der Prozess mit dem Inclusive Gateway nur in den unteren Zweig entartet ist, wurde der Prozess beendet.





Abbildung 6. Entarteter Prozess



Es stellt sich heraus, dass Parallel Gateway das Inclusive Gateway irgendwie beeinflusst. Das ist komisch, unlogisch und sollte es auch nicht sein.



Wie ist das möglich? Es lohnt sich wahrscheinlich, die Theorie darüber, wie Parallel and Inclusive Gateway wieder funktioniert, erneut zu lesen. Was sollte passieren, damit das Join-Gateway alle zusammenbringt und der Prozess fortgesetzt wird? Im Internet schreiben sie, dass jedes sammelnde Inclusive Gateway (Join) darauf wartet, dass dieselbe Nummer eingeht, die die „Gabelung“ verlassen hat. Dann stellt sich plötzlich eine weitere Frage: Wie funktioniert dieser Zähler überhaupt?



Was bist du? Wie arbeitest du?



Dieses Problem verdient Puzzlespiele und intelligente Fernsehsendungen. Nur in Fernsehsendungen dürfen Sie einen Freund anrufen. Andererseits kann ich auch um Hilfe bitten. Wir werden unseren Geschäftsprozessarchitekten Denis anrufen.



- Denis, hallo! Können Sie mir sagen, wie der Sammelweg bestimmt, wann der Prozess fortgesetzt werden muss? Überall schreiben sie: "Wie viel kam heraus - so viel sollte reinkommen." Aber wie genau denkt er das?

- Sehr einfach. Camunda zählt die Anzahl der aktiven Hinrichtungen.

- Vielen Dank.




Überlegen Sie vorerst, was passiert ist. Erinnern Sie sich dazu noch einmal an das ursprüngliche Schema, das sich herausstellte:





Abbildung 7. Hängender Prozess mit einem Standardzweig



Betrachten wir der Einfachheit halber den Fall, in dem alle Bedingungen erfüllt sind. Was haben wir zu dem Zeitpunkt, wenn drei Aufgaben nach diesen Bedingungen erfüllt sind?



Wie viele aktive Hinrichtungen? Drei im unteren und einer im oberen Zweig, wo wir die Zuverlässigkeit des Kunden überprüft haben. Camunda ist es egal, dass dies insgesamt verschiedene parallele Zweige sind. Ich interessiere mich nur für die Anzahl der aktiven Ausführungen, von denen es vier gibt, und das eingehende inklusive Gateway hat nur drei erhalten.



Festsetzung



Um die Situation zu korrigieren, muss das Sammel-Gateway alle Ausführungen auf einmal sammeln, und dann geht der Prozess theoretisch weiter. Versuchen wir, ein statt zwei Join-Gateways zu belassen:





Abbildung 8. Korrigierte Version des Prozesses



Leider sah der Prozess nach den Änderungen meiner Meinung nach weniger offensichtlich aus. Aber es hat wie ursprünglich geplant funktioniert. Nachdem diese Quest erfolgreich beendet war, konnte ich die Änderungen vorantreiben und nach Hause gehen.



Der Spaß fängt gerade erst an



Als ich mich hinsetzte, um diesen Artikel zu schreiben, und ein Beispiel für einen Prozess fand, bei dem ich diesen Fall beschreiben konnte, war ich enttäuscht: Der Prozess funktionierte wie er sollte und es gab keinen Deadlock.



Zuerst habe ich angenommen, dass die Version von Camunda im Beispiel höher ist als im Projekt, und dieses Problem wurde bereits in der neuen Version behoben. Aber die Herabstufung von Camunda hat nichts gebracht. Übrigens wird in allen Beispielen Version 7.8.0 verwendet - es ist weit von der neuesten entfernt, aber es spielt im Prinzip keine Rolle. Das Problem wurde auch in der neuesten Version 7.13 getestet und reproduziert.



Durch Versuch und Irrtum wurde das Problem festgestellt. Das ursprüngliche künstliche Beispiel hatte im Gegensatz zu dem Prozess, den ich am Arbeitsplatz entwickelt habe, keinen umgekehrten Zweig.



Es stellt sich heraus, dass bei Vorhandensein eines umgekehrten Zweigs das Problem reproduziert wird und wir uns in einer Art Deadlock befinden, aber ohne einen umgekehrten Zweig funktioniert alles so, wie es sollte.



Der Fall erforderte Verständnis und Analyse. Dazu musste ich mir die Quellen des Camunda BPM ansehen. Da das Problem beim Inclusive Gateway lag, schien es logisch, in der Klasse nach der Antwort zu suchen, die für das Verhalten dieses Elements verantwortlich ist - InclusiveGatewayActivityBehavior . Nachdem ich einige Male Debug für beide Versionen des Prozesses ausgeführt hatte, fand ich heraus, wie es funktioniert.



Wenn es nicht klar ist - siehe Quellen!



Um kein langweiliges Geschichtenerzählen zu arrangieren, wird die Beschreibung der Arbeit von InclusiveGateway basierend auf dem Quellcode schematisch sein. Die für uns interessante Logik konzentriert sich auf die Methode execute , wobei die Methode activatesGateway für diesen Fall am wertvollsten ist . Soweit ich weiß, wird geprüft, ob das InclusiveGateway übergeben werden kann. Die Ausführungsmethode wird für jede Ausführung (für jeden laufenden Zweig) aufgerufen. In unserem Fall gibt es drei solcher Zweige - dies bedeutet, dass diese Methode dreimal aufgerufen wird.



Mal sehen, wie die Methode activatesGateway funktioniert. Zum besseren Verständnis geben wir allen ausgeführten Zweigen Namen.





Diagramm 9. Prozessdiagramm mit Ausführungen



Nach meinem Verständnis lautet die Logik der Methode wie folgt:Es wird ein Vergleich zwischen der Anzahl der Hinrichtungen, die zu diesem Getty gekommen sind, und der Anzahl der Pfeile gemacht, die in diesem Getty enthalten sind . Diese Prüfung wurde im einfachsten Fall durchgeführt, wenn alle Inclusive Gateway-Zweige ausgeführt werden und die Logik zum Überprüfen des Sammel-Gateways darin besteht, zu warten, bis die Anzahl der eingegebenen Ausführungen der Anzahl der eingehenden Pfeile entspricht. Das heißt, im einfachsten Fall wird die Ausführungsmethode so oft aufgerufen, wie sich Zweige im Sammel-Gateway befinden, und dann wird der Prozess fortgesetzt.



In unserem Fall wird diese Methode dreimal aufgerufen, da die Anzahl der eingehenden Ausführungen von 1 auf 3 steigt. Beim letzten Aufruf beträgt die Anzahl der eingehenden und erwarteten Ausführungen 3 bzw. 4, und wir folgen dem falschen Zweig.



Wenn die Bedingung nicht erfüllt ist, werden die verbleibenden Ausführungen auf Zugehörigkeit zum Inclusive Gateway überprüft. Die Fähigkeit aktiver Ausführungen, zum Join Inclusive Gateway zu gelangen, wird nämlich überprüft.



Hier braucht man etwas Geduld, atmet aus und liest. Die Auflösung ist nah!



Im falschen Zweig der Methode activatesGateway werden bei jedem Aufruf diejenigen, die noch nicht in Inclusive Join-Ausführungen angekommen sind, auf die Möglichkeit überprüft, diesen Join zu erreichen. Wenn mindestens eine Ausführung zu einem Inclusive Gateway führen kann, müssen Sie dies berücksichtigen und warten, bis es auch zu diesem Join kommt. Wenn keine Ausführungen vorhanden sind, die zum Join führen können, gibt die Methode true zurück.



Der interessanteste Teil kommt. Auf den ersten Blick kann die letzte Ausführung (im Diagramm - Ausführung 1) nicht zu Inclusive Gateway führen. Es lohnt sich jedoch, einen Blick auf die Implementierung der canReachActivity- Methode zu werfen , die an dieser Überprüfung beteiligt ist, und der Grund für dieses Verhalten dieses Elements wird klar.



Wenn wir alle Details des Codes verwerfen, wird innerhalb dieser Methode die isReachable-Methode rekursiv aufgerufen, die Schritt für Schritt prüft, ob diese Ausführung in das sammelnde InclusiveGateway gelangen kann. Der umgekehrte Zweig bietet nur eine solche Gelegenheit, und leider wird dies berücksichtigt, obwohl dies nicht der Fall sein sollte, da wir nach allen Verknüpfungen zurückkehren werden.



Infolgedessen wartet Inclusive Gateway auf eine weitere Ausführung, die niemals erfolgen wird. So bekommen wir eine Art Deadlock. Wenn wir die Konventionen fallen lassen, erhalten wir im Prinzip den klassischen Deadlock: Join on Parallel wartet auf die Ausführung des Zweigs mit Inclusive, und umgekehrt wartet der Zweig mit Inclusive auf die Ausführung von Parallel.



Das folgende Diagramm zeigt eine ungefähre Richtung zum Überprüfen der Verfügbarkeit des Inclusive Gateway-Joins ab Ausführung, der über einen parallelen Zweig zum Prallel Gateway kam.





Diagramm 10. Möglicher Pfad von Parallel Join zu Inclusive Join



Das Diagramm zeigt, dass das Join Inclusive Gateway tatsächlich über den Parallel Gateway Join verfügbar ist. Gemäß der Camunda BPM-Logik spielt es keine Rolle, dass bereits eine „Kreisleitung“ vorhanden ist.



Nachdem ich die Gründe herausgefunden hatte, stellte sich unabsichtlich die Frage: Ist dies ein Fehler oder eine Funktion? Meiner Meinung nach ist dies ein Fehler. Jetzt sammle ich Informationen und Fälle, um einen Bericht an das Camunda-Team zu senden.



Es ist gut, dass das Problem lokalisiert ist. Aber was ist jetzt?



Eigentlich jetzt - die Schlussfolgerungen:



  1. Vorgewarnt ist gewappnet. Wir müssen unsere Prozesse unter Berücksichtigung dieses Verhaltens von Camunda aufbauen.
  2. , . parallel join.
  3. Inclusive Gateway , , executions .
  4. , . , Parallel Gateway .


Scheinbare Einfachheit und Klarheit täuschen manchmal. Dies kann nur durch Anhäufung und Replikation von Wissen bekämpft werden. Leider hatte ich zum Zeitpunkt der Lösung dieses Problems keine tiefen Kenntnisse über die Logik von Inclusive Join, also musste ich basteln. Ich habe dieses Wissen durch Ausprobieren, Anrufen eines Freundes und Debuggen der Quellen erlangt.



Daraus folgt eine offensichtliche und keineswegs neue Schlussfolgerung, dass Sie verstehen müssen, wie das von Ihnen verwendete Tool funktioniert. Je besser Sie verstehen, desto weniger solcher Probleme werden auftreten.



Die zweite Schlussfolgerung liegt ebenfalls auf der Hand: Sie müssen nicht nur den Code, sondern auch die Prozesse zerlegen.



Links, die beim Parsen dieses Falls und beim Schreiben eines Artikels hilfreich waren:



  1. Camunda BPM-Quellen
  2. Beschreibung des Inclusive Gateway-Betriebs
  3. Funktionsweise von Parallel Gateway



All Articles