21. September 2022
von Michael Gronau, Lars Nock, Bratislav Milić
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.
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.
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.
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.
Für jedes der getesteten Szenarien starten wir einen Batch von 1.000 Prozessen und messen:
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.
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.
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.
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.
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.
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).
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.
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.
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.
Das könnte Sie auch interessieren