Lastenverteilung für multiple Prozesse

Arne Drews

Mitglied
Hi,

Da es sich hierbei um eine Verständnisfrage handelt, glaube ich im richtigen Unterforum zu sein, ansonsten bitte einfach verschieben, danke.

Wir haben eine Schnittstelle zu einem Partner entwickelt, über die wir bestimmte Aufträge versenden lassen. Für den Start war es vollkommen i.O., die entsprechenden Aufträge nacheinander abzuarbeiten.

Der Ablauf für diese Aufträge ist wie folgt:
Wir laden den Auftrag als Sage-Beleg und passen in den Positionen den Lagerplatz auf das des Partners an. Dann erzeugen wir daraus einen Lieferschein und eine Rechnung. Für Mehrpositionsaufträge kommen noch ein paar Kleinigkeiten dazu, die für die Frage aber nicht relevant sind.

Der Vorgang wird aktuell 4x am Tag ausgeführt, wobei wir im Schnitt aktuell 75 bis 100 Aufträge pro Durchlauf verarbeiten. Das dauert, bedingt durch die Beleganlagen im Schnitt um die 3 bis 4 Minuten.
Da unser Ziel langfristig eine Auftragsmenge von >1000 pro Tag ist, also eine Menge von ca. 200 bis 300 pro Durchlauf, möchte ich das gerne auf einen Thread pro Auftrag aufteilen, um die Verarbeitung parallel zum ApplikationServer senden zu können.

Die Frage:
In wie weit verkraftet der Sage ApplikationServer es, wenn die Anzahl an Anfragen ankommen?

Alternative:
Ich könnte mit asynch arbeiten, allerdings denke ich, dass das kaum Vorteile bringt, denn aufgrund von Fehlerbehandlung und Logauswertung muss ich ja per await auf die Antwort warten, was das ganze aus meiner Sicht nicht performanter machen würde. Beim Multithreading kann ich im jeweiligen Prozess diese Dinge mit abarbeiten, was den Vorteil bringen sollte.

Hat jemand da eine BestPractice oder Tipps, wie man es besser machen kann?
Freue mich über hilfreiche Tipps und Infos.

Danke
Arne
 
Hi nochmal,

wann wird die Auswahl vorgenommen, welche Aufträge an den Partner gesendet werden sollen? Ist beim aktuellen "Anstoßen" noch eine Benutzerinteraktion notwenig, die nicht nur das Drücken auf "Start" verlangt?

Soweit ich die Anforderung verstehe, wäre das mit einem Dienst, der auf dem Server läuft, realisierbar. Hier ist natürlich auch mit Multithreading möglich. Grober Ablauf: Betroffene Aufträge in eine Tabelle speichern und die Daten der Tabelle in einem bestimmten Intervall abrufen. Fehler können dabei natürlich in eine Extratabelle geloggt werden.

Ohne die genauen Anforderungen zu kennen, wird eine genaurere Analyse allerdings schwierig. Hierzu auch gerne via PM und dann per Mail oder Telefonat.

LG
khk
 
Hallo,

Danke für die Antwort.
Mir ist leider nicht ganz klar, was an der Aufgabenstellung unklar formuliert ist?

Es ist keine Interaktion eines benutzers notwendig.
Der Prozess wird Zeit gesteuert über den Aufgabenplaner gestartet und liest quasi alle abrechenbaren Aufträge aus, die über den Partner versendet werden könnten.
Abrechenbar heißt bei uns: Entweder eine Zahlungskondition mit Zahlung nach Lieferung oder das Bezahlt Kennzeichen muss gegeben sein.
Diese Liste an Aufträgen wird durchlaufen und darüber Lieferscheine und Rechnung je Auftrag erstellt. Der Partner bekommt dann eine XML mit den erforderlichen Daten, die in deren System verarbeitet werden können.

Wir sind gerade dabei abzuschätzen, was für Konsquenzen es haben könnte, wenn wir statt Lieferschein und Rechnung nur eine Sofortrechnung machen, damit hätte der ApplikationServer schon mal weniger zu verarbeiten.

Das Verwenden von Multithreading haben wir, wie oben erklärt ja auch bereits intern besprochen. Handicap ist dabei jedoch, dass ich ja auf jeden Thread dennoch warten muss, um auf evtl. Fehler reagieren zu können.
Wenn ich die Fehlerbehandlung in das MT mit rein nehme, wäre das zwar unerheblich, aber aus meiner Sicht redundant?

Die Frage wäre also, wie der ApplikationServer das verarbeitet und welche Variante "schonender" für ihn ist.

Danke
 
Hallo,

danke für die Rückmeldung.

Es ist super schwierig, an der Stelle etwas zu optimieren, da das offizielle Sage-Belegobjekt verwendet werden sollte. Die Performance der Funktionen Beleg.Load(...) und Beleg.Save(...) ist aufgrund der vielen Abhängigkeiten grausam, damit hatten wir auch bereits zu kämpfen.

Die einzige für uns funktionierende Möglichkeit war, alle anderen, eigenen Funktionen zu optimieren und z. B. SQL Bulk Inserting zu nutzen. Auch Updates in großer Menge lösen wir mit SQL Bulk bzw. benutzerdefinierten Tabellentypen.
Für alle SQL-Operationen sollte die ADO.NET-Verbindung genutzt werden, die über das Mandantenobjekt bezogen werden kann. LINQ mit eigenem DataContext unbedingt vermeiden, das verlangsamt die Verarbeitung um ~200 %.

Ich weiß nicht, wie Sie die Protokollierung umgesetzt haben - aber hier besteht z. B. die Möglichkeit Performance zu gewinnen, indem alle Protokolleinträge erst in eine Liste geschrieben und anschließend mittels Bulk Insert in eine SQL-Tabelle geschrieben werden. Natürlich nur für den Fall, dass Sie eine SQL-Tabelle damit füllen.

Ansonsten leidet die Performance laut m. E. am wenigsten, wenn die Belege sequentiell geladen, Folgebelege erstellt und gespeichert werden. Bei Multithreading muss der Threadpool begrenzt werden, da für jeden Thread soweit ich weiß ein weiterer Isolationsprozess erstellt wird - korrigiert mich da bitte, wenn ich falsch liege.
Die Anzahl der Isolationsprozesse ist ebenfalls begrenzt, kann aber für den Application Server in den .config-Dateien angepasst werden (dazu gibt es u. a. empfohlene Werte von Sage je nach Anzahl der User).

Ich freue mich von besseren Lösungen zu lesen!

VG
khk
 
Zurück
Oben