Zum Inhalt springen

Prozess-Handling einer Batch-Datei mittels JSP


Empfohlene Beiträge

Geschrieben

Hallo,

ein blödes Problem erhascht mich bereits am frühen Morgen.

Und zwar habe ich eine JSP-Datei, die mittels "Process p = Runtime.getRuntime().exec(file);" einen Prozess auf dem Server startet. Wenn ich nur einen Client habe, der nicht gleichzeitig mehrmals dieselbe JSP-Datei aufruft, kommt es da zu keinen Problemen (der Prozess darf nur einmal starten, wenn 2 gleichzeititg laufen gibts es fiese Konflikte, die ich nicht abfangen kann).

Nun ist es natürlich so, dass nicht alle Kunden brav warten, bis der Nachbar aus Fernost-Asien die JSP-Datei aufgerufen hat und dann noch 2 Sekunden Karenz duldet bis der Prozess auch wirklich abgeschlossen ist. Nein, sie starten das Script gleichzeitig.

Jetzt komm ich leider mit der Geschichte nicht auf den grünen Zweig, sodass ich sagen könnte "Ich hab das was, was 100%ig läuft" - und das muss es leider auch wirklich. Priorität Nr. 1 ist also, dass der Prozess nur einmal laufen darf.

Meine ersten Ansätze verliefen in Richtung Flags. Ich erzeuge bevor der Prozess anläuft eine temp.-Datei, und lösche sie demnach wieder, wenn der Prozess abgeschlossen ist (der Prozess ist eine Batch-Datei, die am Ende ein delete der Datei auslöst).

Frage ich nun also ab, bevor ich den Prozess starte, ob die temp.-Datei vorhanden ist; Wenn dies der Fall ist, hänge dich in einer While-Schleife auf, und Frage alle Sekunde ab, ob Datei gelöscht ist (wenn Datei gelöscht -> Prozess beendet).

So nun zum eigentlichen Knackpunkt der Story: Gehen z.B. 17 Leute gleichzeitig auf die JSP (unwarscheinlich, aber WENN, ist die K***e am dampfen) sitzen 16 davon in der Warteschleife fest. Nur einer (der Erste) darf den Prozess anschmeißen und setzt diesen Flag (die temp.-Datei), der die Anderen dazu verdonnert in der Schleife zu warten. Warten jetzt also im 1-Sek Abstand 16 Leute darauf, dass eine Datei gelöscht wird, kommt es unweigerlich zu der Tatsache, dass 2 im exakt gleichen Zeitpunkt bemerken "Aha, die Datei ist gelöscht RAUS AUS DER SCHLEIFE".

Und das ist mein Problem, es kommen dann 2 Clients zu dem Entschluss jetzt den Prozess anzuschmeißen, und wie erwähnt darf das nicht der Fall sein.

Es ist mir bisher nicht gelungen ein geeignetes Handling dafür einfallen zu lassen und hoffe daher ein wenig auf Eure Hilfe.

Es muss also explizit der Fall sein, nur 1 Client darf den Prozess anwerfen, alle anderen haben zu warten bis der Prozess beendet ist. Ist er beendet, darf auch nur EIN weiterer Client den Prozess anschmeißen, alle Anderen haben zu warten usw.

Wenn Ihr also Ideen habt, nur her damit; Mir fällt leider nicht gescheihtes mehr dazu ein.

Mfg Tom

Geschrieben

Das Problem nennt sich Synchronisation. Seit jeher hat Java das Schlüsselwort synchronized, das dir hoffentlisch schon mal begegnet ist.

Wenn du die 1.5er benutzt kannst du dir auch mal das Paket java.util.concurrent anschauen. Hier sollte dir die Klasse Semaphore ins Auge stechen.

Beide Möglichkeiten habe den Vorteil das nicht-blockierend warten, wovon der Nutzer nichts merkt, aber dein Server dir dankbar ist.

Geschrieben

Hmm. Vor einiger Zeit habe ich ein Batch-Skript geschrieben, welches verschiedene Prozesse anstößt und zyklisch läuft. Tritt in einem der Prozesse ein Fehler auf, wird eine Datei ERROR.FLAG geschrieben, anhand derer das Skript merkt, daß jeder weitere Durchlauf abzubrechen ist, bis jemand händisch das Problem löst und die ERROR.FLAG wieder löscht.

Das Prinzip läßt sich doch evtl. auf Dein Problem übertragen. Statt Änderungen an der JSP, machst Du Änderungen an der Batch-Datei. Laß' sie zu Beginn prüfen, ob eine Flag-Datei vorliegt. Falls ja, beende die Batch-Datei; falss nein, schreibe ein Flag.

Falls auch das für Dich nicht funktioniert, weil Du entweder keinen Zugriff auf die Batch-Datei hast oder es trotzdem vorkommt, daß 2 Clients die Batch-Datei starten, mußt Du den Aufruf in ein eigenes Objekt schreiben.

Mir fallen da 2 Möglichkeiten ein, die nicht unbedingt stimmen müssen ;)

  1. Du hast ein Singleton-Objekt, das nur eine Methode anbietet, die die Batch-Datei aufruft. Diese Methode ist aber synchronized. So nimmt Dir Java das Handling ab.
  2. Du schreibst eine Warteschlange. Jeder Client, der die Batch-Datei starten möchte, trägt sich in die Liste ein. Die Warteschlange hält die Wartenden in einer Liste und ruft in einem eigenen Thread nach und nach die Batch-Datei auf. Das Problem hierbei ist, daß die Aufrufer keine Bestätigung haben, ob jetzt die Batch-Datei angestoßen wurde oder nicht. Aber auch das läßt sich lösen. Evtl. indem man die Clients, nachdem sie sich eingetragen haben, in einer Schleife laufen läßt. In dieser Schleife wird geprüft, ob der Client selbst noch in der Warteschlange vermerkt ist. Dazu muß natürlich innerhalb der Warteschlange ein geeignetes Client-Identifizierungsmerkmal vorhanden sein.

Eins möcht' ich noch erwähnen: Vielen Dank für diese präzise und ausführliche Problembeschreibung. Erlebt man selten ;)

Geschrieben

Servus,

mein Tipp würde in die ähnliche Richtung gehen wie der meines Vorredners. Du könntest Message Driven Beans verwenden und dort eine Queue-basierte Kommunikation. Die eigentliche Funktionalität (das Anwerfen des Prozesses) macht die MDB. Wenn Du jetzt dafür sorgst, das es nur eine Instanz dieser MDB gibt, dann können Deine Clients den Request einfach absetzen und er wird durchgeführt, wenn er an der Reihe ist.

Peter

Geschrieben
das dir hoffentlisch schon mal begegnet ist.

Ich habe zwar intensiv Java in der Schule gehabt, die Synchronisation war jedoch nie ein Thema, daher kannte ich die Technik nicht.

Habe es nun so gelöst, dass ich am Anfang der JSP-Datei eine Funktion startProcess() aufrufe. In dieser Methode wird zuerst der Prozess p gestartet. Wenn der Prozess gestartet ist, kreiere ich eine Datei (einen temporären Flag), und lasse eine Schleife solange laufen, bis der Flag nicht mehr vorhanden ist. Am Ende des Prozesses (des Batches) wird die temp.-Datei gelöscht, so weiß ich in der Methode, dass der Prozess auch wirklich beendet ist.

Die Methode wurde mit dem Schlüsselwort synchronized versehen.

Leider macht sich im Moment noch ein anderes Problem breit, sodass ich nicht testen kann, ob es einwandfrei funktioniert, wenn ich aber grünes Licht geben kann, melde ich mich nochmal. Vielleicht kann ja der ein oder andere ebenfalls auf mein Problem zurückgreifen.

Mfg Tom

Geschrieben

Würde das ganze mittels Queuing lösen.

Ein Thread arbeitet ein Queue durch und führt nacheinander sämtliche Batchdateien aus.

Will ein Benutzer die Batchdatei starten dann wird sie lediglich in die Queue hinzugefügt. Somit hast du

1) eine sequentielle Abfolge

2) keine Blockvorgänäge ("Bitte warten sie 5Minuten..")

3) keine Konflikte wegen Konkurenz

Alles andere ist imho pfusch und kein Sicherer weg das ganze sinnvoll hinzubekommen.

Ungefähre Beschreibung in Pseudocode:

Auf dem Server liegt eine Komponente QueueHandlich. In separater Thread durchläuft den Queue und bearbeitet eine Anfrage nach der anderen.

Clientseitig:

User x ruft eine JSP y auf. In der JSP soll der Prozess z aufgerufen werden.

Diese "Aufgabe" wird an die Serverkomponente übermittelt und in die Queue gepackt.

Serverseitig:

Ein Thread durchläuft die Queue, ruft den Prozess auf und wartet bis er beendet wird (p.waitFor()). Dann geht's wieder von vorne los.

Das ganz über irgendwelche Dateien zu lösen ist keine sinnvolle Lösung, denn

1) du hast keinen garantierten Zugriff auf eine lokale Platte des Servers

2) brauchst du Lösch-Rechte, um die Flag-Datei zu killen

3) kostet es Zeit jedesmal ne Datei zu erzeugen und wieder zu löschen

4) kann dein Programm abschmieren. Dadurch gibt es die Datei zumindest solange bis der Server neu gestartet wird. Dies wiederum bewirkt dass kein Batchvorgang mehr ausgeführt wird, da durch die existierende Flag-Datei alles blockiert wird.

5) du hast keine sinnvolle Möglichkeit mitzuschreiben wann welcher Prozess gestartet wird. Bei einem Fehler suchst du u. U. tagelang nach dem Fehler, da du ihn keiner Zeit, keiner Batch und keinem User zuordnen kannst.

Geschrieben

Einen wunderschönen guten Morgen wünsche ich.

Ihr habt sehr gute Vorschläge gebracht, ich danke Euch dafür :e@sy

Gelöst habe ich das Problem wiefolgt (und es funktioniert wunderbar): Gleich am Anfang der JSP-Datei rufe ich meinen Prozess p auf und schreibe einen Flag mit einem Timestamp der als erstes in der JSP gesetzt wird. Der Timestamp wird als Parameter an meinen Prozess übergeben.

Nun startet mein Prozess in der Main-Methode, diese ist mit dem Schlüsselwort synchronized versehen.

Wenn mein Prozess durchlaufen ist, lösche ich ganz am Ende des Durchlaufes diesen Flag mit dem übergebenen Timestamp.

Die JSP-Datei hängt sich nach dem Aufruf des Prozesses in eine While-Schleife, die erst wieder freigibt, wenn der Flag (die Datei) mit exakt dem Timestamp gelöscht wird, wie am Anfang festgelegt.

So hat jede JSP-Datei (also jeder einzelne Aufruf der Datei) eine eindeutig zugewiesene "ID" (den Timestamp). Es hängen zwar dann 17, um bei dem Beispiel zu bleiben, Leute gleichzeitig in meinem Prozess, dieser handlet aber intern durch die JVM (synchronized) selbst die Zugriffe auf meine Main-Methode. Es wird sich also brav aneinander gereiht.

Zusätzlich habe ich in der While-Schleife noch die Möglichkeit eingebaut, dass die Schleife nach 20sek abbricht (aus welchem Grunde auch immer) und eine kleine Message erscheint "Timeout - Bitte kurz neu anschmeißen". Neu-anschmeißen beinhaltet dann erneut den Link zur JSP-Datei.

Wie oben schon erwähnt funktioniert diese Methodik (gibts des Wort überhaupt? Keine Ahnung, klingt aber super) einwandfrei, es werden tatsächlich alle JSP-Datei nacheinander aufgebaut, exakt so wie es sein soll.

Mfg Tom

Geschrieben

Schön zu hören/lesen, daß es klappt.

Wie oben schon erwähnt funktioniert diese Methodik (gibts des Wort überhaupt? Keine Ahnung, klingt aber super)

Wenn Du schon fragst, sollst Du auch eine Antwort haben. Laut Wikipedia trifft der Begriff Methodik hier nicht zu. Mit Methode hast Du ein treffendes, auch super klingendes Wort ;)

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...