RAD Technologie & Architektur

yuuvis® RAD 7: Deutliche Ver­bes­serungen in der Workflow-Performance

Geschätzte Lesedauer: 8 Minuten



von Michael Gronau, Lars Nock, Bratislav Milić

Analoge Stoppuhr in Nahaufnahme mit verschwommenem Sekundenzeiger

Bei der Einführung einer neuen Hauptversion eines Produkts ist es üblich, eine Reihe von neuen Funktionen bereitzustellen. Sie lassen sich gut präsentieren und bieten den Benutzern und Systemadministratoren etwas Greifbares. Obwohl sie genauso wichtig sind wie neue Funktionen, bleiben technische Verbesserungen wie Code-Refactoring und Änderungen an der Architektur meist im Verborgenen oder werden bestenfalls als Randnotiz in den Release Notes erwähnt.

In yuuvis® RAD Version 7 haben wir uns jedoch entschlossen, uns auf technische Verbesserungen zu konzentrieren, die Teile des Server-Codes optimieren und die gesamte Systemarchitektur verbessern, wodurch Version 7 in bestimmten Metriken bis zu 5,8-mal schneller ist als Version 6.16 LTS. Dieser Artikel quantifiziert das umfangreiche Refactoring, das wir an der Workflow-Funktionalität in yuuvis® RAD durchgeführt haben, und vergleicht die beiden aufeinanderfolgenden Versionen unseres Produkts, um die Vorteile der neuen Architektur zu demonstrieren.

Workflow in yuuvis® RAD 6

In Version 6 von yuuvis® RAD wurde die Workflow-Logik zwischen zwei Diensten aufgeteilt: Der Kerndienst erledigte den größten Teil der Arbeit und implementierte die Logik jedes Schritts in der Prozessausführung (z. B. Schreiben der Historie, Handhabung der Ersetzungsregeln, Ausführen von Skripten usw.). Der bpm-Dienst steuerte die Aktivitätsverarbeitung innerhalb eines Prozesses (Verschieben eines Prozesses von einem Zustand in einen anderen) und stellte eine REST-Schnittstelle für Clients bereit, um Prozesse aufzulisten, ihre Dateien einzusehen und zu bearbeiten oder die Prozesshistorie abzurufen.

In unserer Performance-Analyse von yuuvis® RAD 6 haben wir festgestellt, dass dieses Setup den von uns angestrebten Grad an Asynchronität einschränkt. Da der bpm-Dienst die Logik enthielt, die den Übergang eines Prozesses in den nächsten Zustand auslöst, musste er einen blockierenden REST-Aufruf machen, der nur diesen Übergang im Kerndienst ausführt. Da der REST-Aufruf den Thread blockierte, bis er beendet war (dies war notwendig, um die korrekte Reihenfolge der Ausführung von Workflow-Schritten zu gewährleisten), konnte der bpm-Dienst seine Threads nicht vollständig nutzen, und der gesamte Workflow-Durchsatz wurde gedrosselt.

yuuvis® RAD 7: Neugestaltung der Dienste und andere technische Verbesserungen

Ab Version 7 haben wir uns für eine striktere Trennung der Zuständigkeiten bei den Diensten entschieden. Der Fokus des bpm-Dienstes liegt nun darauf, den Clients REST-APIs zur Abfrage von Prozessen zur Verfügung zu stellen, während die Logik, die die komplette Ausführung der Prozesse steuert, im Kerndienst zentralisiert ist. Dadurch kann die Inter-Service-Kommunikation, die in yuuvis® RAD 6 auftrat, vollständig vermieden werden.

Der Hauptvorteil der neuen Architekturlösung von yuuvis® RAD 7 ist, dass die Verzögerungen, die durch die Service-zu-Service-Kommunikation über REST entstehen, nicht mehr existieren. Der Zustand eines Prozesses wird mit einem einfachen Aufruf innerhalb des Kerndienstes fortgeschrieben, und die Threads werden nicht mehr für längere Zeiträume blockiert.

Neben Optimierungen in Architektur und Code wurde die Java-Version im yuuvis® RAD Core Service von Java 8 in Version 6 auf Java 11 in Version 7 aktualisiert. Java 11 bringt verschiedene neue Features mit sich, das wichtigste für diesen Artikel ist jedoch der verbesserte Garbage Collector, der die Performance des Kerndienstes nochmals um mehrere Prozent steigert.

Die Verbesserungen auf dem Prüfstand: Setup und Hardware

Für die Ausführung der Benchmarks wurde eine Workstation mit einer Intel Core i7-6700 CPU, 32 GB RAM und einer Samsung PM871a 512 GB SSD verwendet. Der Kerndienst, der die Workflow-Funktionalität ausführt, war durch seine Konfiguration auf nur 2 GB RAM beschränkt. Die von yuuvis® RAD zur Speicherung genutzte Datenbank war MS SQL Server 2014 und wurde auf der gleichen Workstation betrieben.

Benchmark-Methodik

Für jedes der getesteten Szenarien starten wir einen Batch von 1.000 Prozessen und messen:

  • die Gesamtzeit, die für die Ausführung dieses Batches vom Start des ersten Prozesses bis zum Ende des letzten Prozesses im Batch benötigt wird
  • die durchschnittliche Zeit, die für die Ausführung eines einzelnen Prozesses in der Charge benötigt wird, vom Start bis zum Ende

Anschließend führen wir 50 solcher Batches aus und berechnen die Durchschnittswerte für die Gesamtzeit des Batches und für die Ausführung eines einzelnen Prozesses.

Anhand dieser beiden Metriken können wir sowohl die Veränderungen bei der Leistung eines einzelnen Prozesses als auch beim Gesamtdurchsatz des Servers beobachten, wenn mehrere Prozesse parallel ausgeführt werden.

Benchmark-Szenarien

Leeres Modell

Dieses Modell enthält keine Aktivitäten und sein Zweck ist es, die Leistung der Prozesserstellung, des Abschlusses und des Schreibens dieser Ereignisse in die Prozesshistorie zu messen.

Abbildung 1 Gesamtzeit für den Abschluss von 1000 Prozessen für das Szenario “Leeres Modell”

Abbildung 1: Gesamtzeit für den Abschluss von 1.000 Prozessen für das Szenario “Leeres Modell” (in Minuten:Sekunden)

Abbildung 2 Die durchschnittliche Zeit für den Abschluss eines Prozesses für das Szenario “Leeres Modell”

Abbildung 2: Die durchschnittliche Zeit für den Abschluss eines Prozesses für das Szenario “Leeres Modell” (in Minuten:Sekunden)

Dieser Benchmark zeigt deutlich die verbesserte Auslastung der verfügbaren Threads in den entsprechenden Diensten. Während die Ausführungszeit eines einzelnen Prozesses vergleichbar ist (was zu erwarten ist, da die ausgeführten Schritte ähnlich sind – Initialisieren und Beenden eines Prozesses und Schreiben von Verlaufseinträgen in die Datenbank), sehen wir eine enorme Verbesserung der Gesamtausführungszeit für einen ganzen Stapel. Version 7 ist in der Lage, Prozesse effizient parallel auszuführen, wodurch sich die Ausführungszeit um den Faktor 5 verkürzt. Wie bereits erläutert, verlor Version 6 Zeit bei der REST-Kommunikation zwischen den Diensten, wodurch der Gesamtdurchsatz gedrosselt wurde.

Sequenzielles Modell

Dieses Modell enthält neun Routen (in Bezug auf den prozesslogischen Overhead ist es äquivalent zu einem leeren Benutzer-Workitem in yuuvis® RAD, aber einfacher zu benchmarken, da keine Benutzeraktion erforderlich ist, um es zum nächsten Schritt zu bewegen). Der Zweck dieses Modells ist die Messung und Quantifizierung der Leistung der Weiterleitung von Aktivitäten. Es ist repräsentativ für Modelle, die mehrere benutzerbezogene Aufgaben enthalten, ohne dass intensives Skripting in Work-Item-Ereignissen ausgeführt wird, um komplexe Geschäftslogik zu implementieren, wobei der größte Teil der Systemlast durch den Prozessübergang von einem Schritt zum nächsten entsteht.

Abbildung 3 Sequenzielles Modell

Abbildung 3: Sequenzielles Modell

Abbildung 4 Gesamtzeit für den Abschluss von 1000 Prozessen für das Szenario “Sequenzielles Modell”

Abbildung 4: Gesamtzeit für den Abschluss von 1.000 Prozessen für das Szenario “Sequenzielles Modell” (in Minuten:Sekunden)

Abbildung 5 Die durchschnittliche Zeit bis zum Abschluss eines Prozesses für das Szenario “Sequenzielles Modell”

Abbildung 5: Die durchschnittliche Zeit bis zum Abschluss eines Prozesses für das Szenario “Sequenzielles Modell” (in Minuten:Sekunden)

Die Ergebnisse bestätigen die Ergebnisse des ersten Benchmarks: Die Aktivitäten werden in Version 6 während der Kommunikation zwischen bpm-Dienst und Kerndienst verzögert, während Version 7 von einem höheren Grad an paralleler Ausführung und einer schnelleren Auslösung des Prozessfortschritts durch seine Zustandsmaschine profitiert. Wir können sehen, dass die Ausführungszeiten eines einzelnen Prozesses in beiden Versionen mit der Gesamtausführungszeit des gesamten Batches vergleichbar sind. Dies deutet darauf hin, dass die meisten Prozessinstanzen gleichzeitig vorhanden sind und verarbeitet werden. Die Version 7 profitiert jedoch wiederum von dem geringeren Overhead der Kommunikation zwischen den Diensten und kann einen Batch wesentlich schneller abschließen.

Skript-Modell

Das Skript-Modell enthält nur einen Schritt mit einer einzigen Aktivität und einem zugehörigen Skript. Wir verwenden die Route aus demselben Grund wie im Szenario “Sequenzielles Modell”: um die Weiterleitung der Prozessschritte zu automatisieren. Die Aktivität enthält ein einfaches BeforeStartActivity-Skript, das einige Einträge in das Serverprotokoll schreibt und dann 500 ms lang schläft (Abbildung 7).

Abbildung 6 Skript-Modell

Abbildung 6: Skript-Modell

var p = $.process;
// log some attributes of the 'process'...
$.log.info('processId:    ' + p.id);           // id of the process
$.log.info('creator:      ' + p.creator.id);   // id of the user who started the process
$.log.info('creationTime: ' + p.creationTime); // time when the creator started the process
java.lang.Thread.sleep(500);
$.done();

Abbildung 7: BeforeStartActivity-Skript, das eine typische Skriptlast auf dem Server emuliert

Der Zweck dieses Modells besteht darin, die Leistung der Skriptverarbeitung zu messen. Die Verarbeitung eines Skripts blockiert den Server-Thread während seiner Ausführung, sodass wir sowohl das Verhalten des Servers bei hoher Skriptlast als auch die Auslastung der verfügbaren Threads quantifizieren können. Es ist auch ein repräsentatives Modell für stark skriptbasierte Modelle, die komplexe Geschäftslogik implementieren. Außerdem wurde, wie bereits erläutert, ein Teil der Verarbeitungslogik in den Kerndienst verlagert, was zu einem wesentlich geringeren Kommunikations-Overhead führt. Dies erhöht jedoch die Verarbeitungslast des Kerndienstes in Version 7, da er nun auch die Zustände des Prozesszustandsautomaten umwandeln muss. Eine Aufgabe, die in Version 6 vom bpm-Dienst ausgeführt wurde. Daher war es wichtig zu evaluieren, ob diese geringfügige Erhöhung der Verarbeitungslast die Leistung von rechenintensiven Prozessen beeinträchtigen kann und somit die positiven Effekte, die in den zuvor analysierten Szenarien beobachtet wurden, zunichtemacht.

Abbildung 8 Gesamtzeit bis zum Abschluss von 1000 Prozessen für das Szenario “Skript-Modell”

Abbildung 8: Gesamtzeit bis zum Abschluss von 1.000 Prozessen für das Szenario “Skript-Modell” (in Minuten:Sekunden)

Abbildung 9: Durchschnittliche Zeit bis zum Abschluss eines Prozesses für das Szenario “Skript-Modell”

Abbildung 9: Durchschnittliche Zeit bis zum Abschluss eines Prozesses für das Szenario “Skript-Modell” (in Minuten:Sekunden)

Der Benchmark zeigt, dass die Version 7 in diesem Szenario keine Rückschritte macht und ihre Vorteile gegenüber der Version 6 beibehält. Von besonderem Interesse ist die Messung, die zeigt, dass die Gesamtausführungszeit eines Stapels in einem System mit 4 Verarbeitungsthreads in Version 7 nur 27 % langsamer ist als die Ausführungszeit eines Stapels in einem System der Version 6 mit 8 Threads.

Dies kann von Systembetreibern genutzt werden, um entweder den Workflow-Durchsatz in Systemen mit Version 7 zu verbessern (indem sie eine hohe Anzahl von Threads für den Kerndienst und die Workflow-Verarbeitung beibehalten). Der Betreiber kann sich auch dafür entscheiden, ein vergleichbares Leistungsniveau wie in Version 6 beizubehalten. Dies kann erreicht werden, indem das System in Version 7 so rekonfiguriert wird, dass es mit nur 4 Threads läuft und die verbleibenden vier Threads anderen rechenintensiven Aufgaben im yuuvis® RAD-System zugewiesen werden.

Zusammenfassung

In Version 7 haben wir die Architektur optimiert und den Kommunikations-Overhead zwischen den Microservices reduziert, um die Gesamtleistung der Workflows zu verbessern.

Die mit Version 7 erzielten Verbesserungen sind beträchtlich und in allen analysierten Szenarien konsistent. Sie betreffen sowohl die Leistung eines einzelnen Prozesses (Zeit, die benötigt wird, um einen einzelnen Prozess in einem Batch abzuschließen) als auch den Gesamtdurchsatz des Systems (Zeit, die benötigt wird, um einen Batch von Prozessen abzuschließen).

Bei Workflow-Modellen, die in ihren Skripten eine geringe Verarbeitungslast erzeugen, beobachten wir beispielsweise die größten Verbesserungen – Version 7 ist bis zu 5,8-mal schneller als Version 6.16 LTS. Bei verarbeitungsintensiven Workflows, die komplexe Geschäftslogik in ihren Skripten enthalten, ist es nicht möglich, die Skriptlaufzeit zu reduzieren (die Logik in den Skripten muss einfach ausgeführt werden). Aber auch in diesem Fall profitiert die Version 7 von den durchgeführten Optimierungen und bleibt in jeder analysierten Metrik schneller als die Vorgängerversion von yuuvis® RAD.