Camunda BPM External Task Worker und Quarkus

Mittwoch, 2.11.2022

Quarkus-and-camunda-external-task-workers

In der Prozessautomatisierung mit Camunda Platform 7 wird häufig das External-Task-Pattern verwendet, um die Orchestrierung von Tasks und deren Ausführung zu entkoppeln. Bei diesem Pattern erfolgt die Ausführung eines Tasks durch einen sogenannten External-Task-Worker, d.h. eine kleinere Anwendung, die getrennt von der Prozess-Engine deployt und ausgeführt werden kann. So kann sie unabhängig und damit genauer auf die Bedürfnisse des Tasks skaliert werden. Um wirklich von dieser Funktion profitieren zu können, muss die externe Task-Worker-Anwendung leichtgewichtig genug sein, um schnelle Auf- und Abwärtsskalierung zu ermöglichen, ohne dabei große Kosten zu verursachen. Das Java-Framework Quarkus ist ideal geeignet, um kleine, leichtgewichtige Java-Anwendungen zu erstellen, und unsere neue Quarkus-Erweiterung macht es viel einfacher, External-Task-Worker in diesem Frameworks zu implementieren.


Entkopplung und Camunda-Architektur

In der Prozessautomatisierung favorisiert Camunda mehr und mehr die Entkopplung von Aufgabenorchestrierung und -ausführung. Anfang 2022 hat Camunda seine Architekturempfehlungen aktualisiert, um die Tatsache widerzuspiegeln, dass sie nun eine Trennung von Prozess-Engine und Ausführungscode bevorzugen, im Gegensatz zu ihrer früheren bevorzugten Architektur von Prozess-Engines, die in Prozessanwendungen integriert sind. Camunda-Mitgründer Bernd Rücker erklärt die Gründe für diesen Sinneswandel in einem aufschlussreichen Blogbeitrag. Für die Camunda Platform 7 wird diese Entkopplung durch die Verwendung des External-Task-Worker-Patterns erreicht, bei dem Aufgaben asynchron von unabhängigen Anwendungen, den External-Task-Workers, ausgeführt werden. Dieses Muster bietet eine Reihe von Vorteilen, wie z.B. die Trennung von Zuständigkeiten, bessere Skalierung oder - bis zu einem gewissen Grad - Unabhängigkeit von Programmiersprachen.
NB: Die Entscheidung von Camunda, die Orchestrierung und Ausführung von Prozessen bevorzugt zu entkoppeln, steht im Einklang mit dem Release von Camunda 8 im April 2022. In diesem Cloud-basierten Produkt wird die Trennung von Engine und Ausführung durch das Design erzwungen. In den nächsten Jahren werden Camunda 8 und Camunda 7 als zwei getrennte, aber verwandte Produkte koexistieren. Die Verwendung von externen Tasks in Camunda 7 (für die unsere Quarkus-Erweiterung entwickelt wurde) wird jedoch einen möglichen zukünftigen Übergang zu Camunda 8 erheblich erleichtern, wie man auch einem weiteren Blogbeitrag von Bernd Rücker entnehmen kann.

Exkurs: Camunda 7 oder Camunda 8?

Mit den Unterschieden von Camunda 7 und Camunda 8 befassen wir uns in unserem großen Vergleich Camunda 7 vs. Camunda 8: Wo liegen die Unterschiede.

 

Grundlagen des External-Task-Worker-Patterns

Das Konzept der External-Task-Worker haben wir bereits in einem unserer früheren Blogbeiträge  recht ausführlich erläutert. Kurz gesagt: Ein BPMN-Prozess wird mit Hilfe der Camunda Process-Engine automatisiert. Die Engine kümmert sich um die korrekte Reihenfolge der Schritte innerhalb des Prozesses und stellt sicher, dass an jedem Punkt die richtige Aufgabe ausgeführt wird, woraufhin die Prozessinstanz auf dem richtigen Weg weiterläuft. In klassischen Prozessanwendungen wäre der Ausführungscode für diese Aufgaben normalerweise Teil derselben Java-Anwendung, die bereits die Prozess-Engine enthält (oder zumindest auf demselben Anwendungsserver wie diese läuft). Dies ist beim External-Task-Worker-Patternnicht der Fall. Stattdessen ist der Ausführungscode Teil einer separaten, unabhängigen Anwendung, die die REST-API der Prozess-Engine nutzt, um offene Tasks für ein bestimmtes Topic abzurufen, die in dem Task vorliegende Arbeit auszuführen und das Ergebnis dann wieder über die REST-API zurückzugeben. Die Process-Engine kümmert sich also nicht mehr darum, wie die Tasks ausgeführt werden, sondern nur noch darum, dass sie ausgeführt werden.

NB: Wenn Sie sich tiefergehendmit dem Thema External-Task-Worker auseinander setzen wollen, könnte auch unser Blogpost  Camunda External Tasks - Fehlerverhalten implementieren interessant für Sie sein.

 

External Task Worker und die Cloud: Wie  Für einander gemacht

Einer der Hauptvorteile des External-Task-Patterns ist, dass die Worker-Applikationen (im Allgemeinen) viel kleiner sind als die klassischen, üblicherweise recht großen vollständigen Prozessanwendungen. Darüber hinaus können sie unabhängig von der Process-Engine rauf- und runter skaliert werden, so dass z. B. in Zeiten hoher Arbeitsbelastung viele Instanzen zur Verfügung stehen und andererseits keine Instanzen laufen, wenn in absehbarer Zeit keine Arbeit anfällt. Diese beiden Eigenschaften machen External Task Worker-Anwendungen zu idealen Kandidaten für den Einsatz in der Cloud, z. B. in Kubernetes-Clustern, wo die Skalierung kleiner Anwendungen zwingend erforderlich ist.

 

Implementierung von External Task Workern

Da die External-Task-Worker im Wesentlichen nur in der Lage sein müssen, über REST mit der Prozess-Engine zu kommunizieren, können sie in so gut wie jeder verfügbaren Programmiersprache implementiert werden. Entwickler, die in den letzten Jahren mit Camunda gearbeitet haben, sind jedoch in der Regel an die Arbeit mit Java gewöhnt. Daher werden viele von ihnen External-Task-Worker auch in dieser Sprache implementieren wollen. Camunda ist sich dessen bewusst und bietet mit dem Camunda External Task Client eine Java-Bibliothek an, die einen Großteil des Overheads übernimmt, der durch die Nutzung der REST-API sowie durch das kontinuierliche Polling neuer Aufgaben entsteht. Mit dieser Bibliothek reduziert sich die Implementierung einer External-Task-Worker-Anwendung auf die folgenden wenigen Schritte:

  1. Erstelle und konfiguriere eine Instanz der Klasse ExternalTaskClient.
  2. Implementiere das Interface ExternalTaskHandler und führe in dessen execute-Methode aus, was für die Geschäftslogik des jeweiligen Tasks notwendig ist.
  3. Registriere eine Instanz der in Schritt 2 implementierten Klasse bei der Instanz des ExternalTaskClient unter dem Topic des zugehörigen Tasks

Sobald der ExternalTaskClient gestartet ist, wird er die Process-Engine kontinuierlich nach neuen Tasks für dieses registrierte Topic abfragen. Sobald neue Aufgaben verfügbar sind, holt er sie ab und verwendet den registrierten TaskHandler, um die Aufgaben auszuführen und abzuschließen. Zusätzliche nützliche Funktionen wie eine Backoff-Funktionalität für das Task-Polling sind ebenfalls Teil dieser Bibliothek.

Die Schritte 1 und 3 sind im Wesentlichen Boilerplate, da sie für jede neue External-Task-Worker-Anwendung implementiert werden müssen, obwohl sie sich nie wirklich ändern. Daher bietet Camunda auch einen Spring Boot Starter an, der die Schritte 1 und 3 übernimmt und es erlaubt, ExternalTaskHandler-Implementierungen einfach über eine Annotation zu registrieren. Auf diese Weise wird die Implementierung von External-Task-Worker-Anwendungen recht komfortabel. Leider sind Java-Anwendungen und insbesondere Spring-Boot-Anwendungen dafür bekannt, relativ groß und langsam zu sein, insbesondere bei ihrem Start. Daher ist dieses Setup nicht wirklich geeignet, um die oben erwähnten Vorteile des External-Task-Worker-Patterns zu nutzen, die sich daraus ergeben, dass Anwendungen leichtgewichtig und schnell sind.

 

Quarkus Schafft Abhilfe

Die Tatsache, dass Spring Boot-Anwendungen aufgrund ihres trägen Verhaltens nicht ideal für den Einsatz in Kubernetes-Clustern sind, ist natürlich nicht wirklich neu. Um dieses Problem zu lösen und kleinere und schnellere Java-Anwendungen schreiben zu können, sind in den letzten Jahren mehrere neue Frameworksentwickelt worden, unter anderem  Micronaut, Spring Native und Quarkus. Diese Frameworks versprechen allesamt, extrem kleine und schnell startende Anwendungen zu liefern, indem sie sogenannte nativer Kompilierung verwenden. Allerdings führen die Frameworks bereits bei normaler Kompilierung zu kleineren Anwendungen mit schnelleren Startzeiten in normalen JVM-Deployments als Spring Boot sie bieten kann, vgl. z.B. hier.

 

Quarkus External Task Worker Extension

Um Entwicklern die Implementierung von External-Task-Worker-Anwendungen in Quarkus zu erleichtern, haben wir eine kleine Quarkus-Erweiterung geschrieben. Sie basiert auf der ExternalTaskClient-Bibliothek von Camunda und übernimmt wie der Camunda-eigene Spring-Boot-Starter im Wesentlichen die oben genannten Schritte 1 und 3, also die Konfiguration und Instanziierung eines ExternalTaskClients sowie die automatische Registrierung von ExternalTaskHandler-Beans für ein Topic mittels einer geeigneten Annotation. Zusätzlich wird der instanziierte ExternalTaskClient als Bean im Quarkus-Anwendungskontext verfügbar gemacht, um z.B. neue Handler zu registrieren oder die Ausführung von Tasks zur Laufzeit zu starten bzw. stoppen.

 

Bringt das Was?

Setup

Um unsere Extension zu testen, haben wir den unten abgebildeten kleinen BPMN-Prozess mit Camunda automatisiert.

Process_External_Task_Worker

 

In diesem Setup haben wir haben uns für das folgende Szenario entschieden:

  1. Die obige Prozessdefinition wird auf einer Camunda Process Engine deployed, die alle 20 Sekunden eine Prozessinstanz startet.
  2. Der erste Service-Task wird von einemExternal-Task-Worker bearbeitet, der mit Quarkus und unserer neuen Erweiterung entwickelt wurde.
  3. Der zweite Service-Task wird von einem External-Task-Worker bearbeitet, der mit Spring Boot erstellt wurde.
  4. Die Process-Engine und die Worker laufen als separate Pods auf einem K8s-Cluster
  5. Wir haben das Setup insgesamt 5 Mal gestartet und den Durchschnitt über diese Läufe ermittelt

 

Ergebnisse

Die beiden wichtigsten Kennzahlen, die wir vergleichen wollen, sind die Startzeit der Worker-Applikationen und ihre RAM-Nutzung während der kontinuierlichen Ausführung ihrer jeweiligen Service-Tasks.

Die folgende Tabelle zeigt die Startzeiten der Worker-Applikationen während unserer 5 Experimentdurchläufe in Sekunden sowie deren Durchschnitt:

 

  Quarkus External Worker Spring Boot Worker
Startup #1 1.958 3.376
Startup #2 2.578 2.830
Startup #3 1.325 2.630
Startup #4 1.736 2.350
Startup #5 1.720 2.128
Durchschnitt ~ 1.863 ~ 2.662

 


Wie wir sehen, starteten die Quarkus-Anwendungen deutlich schneller als ihre Spring-Boot-Pendants.

In ähnlicher Weise haben wir die RAM-Nutzung der Anwendungen während unserer Experimente verfolgt.

Comparison of memory usage between Spring Boot and Quarkus external task worker applications

 

Auch hier ist leicht zu erkennen, dass Quarkus auch in dieser Kennzahl deutlich besser abschneidet als Spring Boot.

 

Wie nutze ich die Extension?

Um unsere neue Quarkus-Extension zu verwenden, muss sie wie üblich als Abhängigkeit bereitgestellt werden, z.B. in der pom.xml eines Maven-Projekts:

 

Die application.properties (oder application.yaml) kann dann verwendet werden, um die Erweiterung zu konfigurieren und insbesondere die Verbindung zur Process-Engine sowie eine worker-id zu konfigurieren, z.B.

de.viadee.camunda.client.base-url=http://localhost:8080/engine-rest

de.viadee.camunda.client.worker-id=my-example-worker

Es gibt noch eine ganze Reihe weiterer Optionen zu konfigurieren, aber das sollte fürs Erste genügen. Wie üblich müssen wir nun einen ExternalTaskHandler implementieren, der sich um die eigentliche Geschäftslogik kümmert, die wir mit diesem Worker erreichen wollen.






Hier sind eigentlich nur die ersten beiden Zeilen erwähnenswert. Erstens verwenden wir @ApplicationScoped, um dafür zu sorgen, dass Quarkus eine Bean für diese Klasse erstellt (im Wesentlichen analog dazu, wie man z.B. @Component in Spring Boot verwenden würde). Die Annotation @ExternalTaskSubscription ist Teil unserer Extension. Beim Start der Anwendung werden alle Beans, deren Klasse mit dieser Annotation versehen ist, beim ExternalTaskClient unter ihrem durch topicName angegebenen Topic registriert. Dann beginnt der Client mit der Abfrage von Tasks und verwendet diese Handler-Implementierung, um sie auszuführen und abzuschließen - das war's!


Open SOurce

Der gesamte Quellcode unserer Erweiterung ist auf GitHub zu finden. Der Ordner /example enthält ein kleines praktikables Beispiel für die Verwendung der Erweiterung. Die External Task Client Extension für Quarkus ist ein Open Source Projekt, das unter der BDS3-Clause License veröffentlicht wird. Natürlich ist jeder herzlich eingeladen, sich auf GitHub zu beteiligen, entweder durch Verbesserungsvorschläge über die Projekt-Issues oder durch direkte Mitarbeit am Code per Pull Request.

 

Nächster Halt: Native Kompilierung

Wie oben beschrieben kann Quarkus auch für die native Kompilierung mit der GraalVM verwendet werden, um extrem kleine und schnelle Anwendungen zu erstellen, die ohne JVM laufen. Allerdings ist ein gewisser Mehraufwand erforderlich, um nativ kompilierte Quarkus-Anwendungen tatsächlich sauber und vollständig zum Laufen zu bringen. Insbesondere müssen alle Klassen, auf die Reflection zur Laufzeit angewendet wird, bereits zur Build-Zeit bekannt sein und als entsprechend markiert werden. Dies betrifft vor allem die Verwendung von praktisch allen (De-)Serialisierungsbibliotheken.
Unsere External-Task-Worker-Extension ist noch nicht vollständig kompatibel mit der nativen Kompilierung und Anwendungen, die sie verwenden, werden auf einige Schwierigkeiten stoßen. Es ist jedoch definitiv ein Meilenstein für eine der kommenden Versionen!

 

PROCESS MANAGEMENT Direkt in Ihrem Confluence

Kennen Sie unseren viadee BPMN Modeler für Confluence? Als einfach zu installierendes und zu nutzendes Plugin für das Enterprise Wiki System Atlassian Confluence ermöglicht der viadee BPMN Modeler, methodisch tiefgreifendes Prozessmanagement direkt in Confluence durchzuführen. Die zahlreichen und wertvollen Vorteile dieses Ansatzes resultieren aus der umfangreichen Projekterfahrung unserer BPM-Experten und waren die Motivation für die Entwicklung des Plug-ins.

Besuchen Sie unsere BPMN Modeler Seite oder Testen sie das Plugin direkt über den Atlassian Marketplace.


zurück zur Blogübersicht

Diese Beiträge könnten Sie ebenfalls interessieren

Keinen Beitrag verpassen – viadee Blog abonnieren

Jetzt Blog abonnieren!

Kommentare

Christoph Schönnenbeck

Christoph Schönnenbeck

Dr. Christoph Schönnenbeck ist seit 2019 Berater bei der viadee. Sein Schwerpunkt liegt im Business Process Management und der Prozessautomatisierung insbesondere im Cloud-Umfeld.

Christoph Schönnenbeck bei LinkedIn