PDA

View Full Version : Möglichkeit Timeout bei ProgrammCall



Seiten : [1] 2

arminius
13-06-06, 08:19
Wer kann mir hier helfen? Wir haben ein Programm entwickelt, das mittels eines ProgrammCalls Funktionalitäten auf der AS/400 anstartet. In diversen Fehlersituationen kommt der Aufruf xxx.run nicht zurück. Besteht die Möglichkeit über Mittel der Toolbox einen Timeout zu definieren? Gibt es zu dem Methodenaufruf run Alternativen?

Fuerchau
13-06-06, 14:44
Das kannst du nur per separatem Thread erledigen, der nach vorgegebener Zeit ein Wecksignal schickt.

Aber Achtung:
Der Job auf der AS/400 läßt sich dadurch normalerweise nicht canceln sonder läuft dann eben ohne Verbindung erst mal weiter !

RobertPic
13-06-06, 16:03
EDIT: Ich sehe Fuerchau war schneller, dafür gibt's gleich ein Beispiel.

Laut API bieten ProgrammCalls kein Timeout.

Für den genauen Ratschlag müsste ich noch wisssen, ob du das Programm auf der AS/400 oder woanders läuft...

Unabhängig davon, aber die 2 Möglichkeiten:

1. via JDBC-Connection und CallableStatement. Dort gibt es ein Querytimeout. Um das Programm in eine StoredProcedure binden, suche im Forum.

2. einen Überwachungsthread starten

etwas so wie hier:


int waitSec = 900;
int killTime = 30;

Thread timeGuard = new Thread(new TimeGuard(waitSec+killTime, Thread.currentThread()));
try {
this.log("*** Warte auf Arbeit .... ***");
timeGuard.start();
DQData = dq.read(waitSec);
} catch (InterruptedException e ) {
this.log ( "TimeOut - Wiederanlauf in 2 Minunten" );
.....
} finally {
timeGuard.interrupt();
}

Hier die Klasse Timeguard:



public class TimeGuard extends Thread {

private long waitTime;
private Thread callThread;

public TimeGuard (int waitTimeSec, Thread callThread) {

this.waitTime = waitTimeSec * 1000;
this.callThread = callThread;
}

public void run() {
try {
Thread.sleep(waitTime);
callThread.interrupt(); // Timeout, Caller unterbrechen

} catch (InterruptedException e) {
// Normalfall
}
}
}

Einschränkung: Wenn man es ganz genau haben will, müsste man noch um ein Syncobject einbauen.

Ich hab schon irgendwo eine elegantere Lösung gesehen, lebe mit der aber auch ganz gut.

Falls es noch Fragen gibt nur zu.

Robert P.

PS. Wie man an diesem Beispiel sieht, läßt einen das Timeout der DataQueues auch im Stich, wenn der Listener am PC läuft und die AS/400 z.B. niederfährt --> ohne Timeout wartet der Listener dann ewig (auch wenn neue Einträge in die Dataqueue kommen würden)

Fuerchau
13-06-06, 16:49
Ob ein QueryTimeout auf eine Stored-Procedure funktioniert, habe ich noch nicht ausprobiert.

Allerdings läuft ein CALL SQL-Procedure in einem anderen Job als CALL Programm und unterliegt auch anderen Regeln !!!

Ausserdem muss die Procedure dann für die AS/400 ThreadSave sein, da sonst kein Timeout-Thread gestartet werden kann.
Also kein Aufruf von RPG's, CLP's usw. sondern ausschließlich C bzw. native SQL-Prozeduren, die als Threadsave deklariert wurden.

RobertPic
13-06-06, 18:07
Ob ein QueryTimeout auf eine Stored-Procedure funktioniert, habe ich noch nicht ausprobiert.


Hab es mal schnell ausprobiert:
Bei der stored Procedure mit CL-Programm wird es ignoriert.

Bei der native SQL-Procedure fängt er zu schätzen an.....

Es bleibt wirklich nur die Überwachungsvariante vom Aufrufer.

Zum Canceln: Man kann die Wahrscheinlichkeit erhöhen, wenn man ein Reconnect (Objekt as400) durchführt. Diverse Perfomanceoptimierungen können einen dabei aber in die Suppe spucken...

Robert P.

Fuerchau
13-06-06, 20:21
Im Falle eines nötigen Cancels sollte man die Verbindung komplett freigeben und vom Garbagecollector auflösen lassen.
Ein Reconnect könnte auch Resourcenprobleme bereiten, eine nagelneue Verbindung bekommt sicherlich auch einen neuen Job.
Achtung Ausnahme: ConnectionPooling !!!

RobertPic
13-06-06, 20:57
Im Falle eines nötigen Cancels sollte man die Verbindung komplett freigeben und vom Garbagecollector auflösen lassen.
Ein Reconnect könnte auch Resourcenprobleme bereiten...
Mit Reconnect war auch close und neues Connect gemeint - die Klasse AS400 hat gar kein reconnect.

Anbei gleich den Code:



// Wiederaufbau der AS/400-Verbindung (z.B. für DataQueue)
public void reconnect () {
if (as400 != null) {
as400.disconnectAllServices();
as400 = null;
}
as400 = new AS400(sysname, username, password);
}



Robert P.

BenderD
15-06-06, 10:39
Hallo,

ich spüre da so ein leichtes Kräuseln meiner Nackenhaare, wenn ich das richtig verstanden habe, dann habe ich einen Java Client, der einen AS400 Serverdienst aufruft (sei es nun ein call via AS400 Objekt, oder ein JDBC Call), der seinerseits irgendwie hängen bleibt, oder nicht in die Pötte kommt. Solange dieses AS400 Programm vor sich hin dümpelt, solange wird kein Garbage Collector es wegräumen, vermutlich funzt dann nicht mal finalize und dann müllt sich das ganze mit womöglich ewig hängenden Leichen zu. Den Ansatz das auf dem Client zu monitoren und von dort den Thread aufzugeben, das würde ich bleiben lassen.
Auf dem Server einen Monitor einzubauen, scheitert vermutlich daran, dass es sich um einen RPG Schinken handelt, deer keinen Monitor Thread hat und haben kann.
Ich würde hier ganz entschieden für ein Redesign und neu schreiben der AS400 Seite plädieren (wahrscheinlich liest der eh nur aus der Datenbank). Sollte das absolut nicht gehen, weil keiner mehr weiß, was dieses Teil treibt, oder selbiges solch wertvolle Gedanken enthält, auf die man kein zweites Mal kommt, dann wäre das eine der ganz abgezählten Ausnahmen in denen ich auf die synchrone Variante setzen würde:
- aus Java per JNI aufrufen
- Monitor Thread in Java
- bei timeout Exception Aufruf abbrechen
- das RPG Teil keinesfalls mit Thread serializable wandeln
- nach Abbruch das Java Objekt dem Garbage Kollektor überlassen

Bei Stresstests dieser Art würde ich immer das AS400 Objekt meiden und selbiges nur über den jt400 Treiber versuchen, auch vom native Treiber würde ich hier wg. Buggy Syndromen die Finger lassen.

@Baldur: die Thread Safe Sache hat mit der Möglichkeit einen Thread zu starten nix zu tun. Der Job (in dem das Java Teil läuft) muss Multithreading erlauben, das Subsystem muss über entsprechende Anzahl von activity levels verfügen, das Subsystem muss einen eventuell zusätzlichen Qshell Job erlauben und das wars. Thread *serializable bewirkt lediglich, dass man nicht zweimal gleichzeitig in dasselbe Modul reinkommt, die Aufrufe werden geblockt, bis der, der gerade dran ist, zurück kommt. Das ist sowohl unzureichend (export von Variablen), wie gefährlich (Verklemmungen durch Deadlocks).

@Robert: wenn ich das richtig verstehe, brauchst du den Monitro Mechanismus nur, weil die DTAQ Implementierung der Toolbox nicht das tut, was sie soll?! die soll doch gerade nach waitSec aufhören, wie sie das mit AS400 API auch tut.

mfg

Dieter Bender

PS: die rein AS400 seitige Lösung über Zwischenschaltung einer DTAQ wäre vielleicht sogar noch das beste:
- Aufuf eines AS400 Programms per JDBC
- selbiges stellt eine Anforderung in eine DTAQ und wartet n sek auf Antwort
- wenn der wait zuschlägt Rückgabe an Java Programm "wwn" (war wohl nix) und Abbruch des RPG Schinkens




Im Falle eines nötigen Cancels sollte man die Verbindung komplett freigeben und vom Garbagecollector auflösen lassen.
Ein Reconnect könnte auch Resourcenprobleme bereiten, eine nagelneue Verbindung bekommt sicherlich auch einen neuen Job.
Achtung Ausnahme: ConnectionPooling !!!

RobertPic
16-06-06, 11:42
@Robert: wenn ich das richtig verstehe, brauchst du den Monitro Mechanismus nur, weil die DTAQ Implementierung der Toolbox nicht das tut, was sie soll?! die soll doch gerade nach waitSec aufhören, wie sie das mit AS400 API auch tut.


Genau. Prinzipiell funktioniert die Wartezeit bei der Toolbox. Der Wartemechanismus ist aber nur serverseitig implementiert.

Das eigentliche Problem ist aber, dass der DataQueue.read keine Exception wirft, wenn die AS/400 weg ist (und die Javaprogramme auf Windows- bzw. Linux laufen). Der Job bleibt auf warten, auch wenn die AS/400 schon längst wieder da ist und neue Einträge warten.

Daher meine "Hurra ich lebe noch" Kontrolle für meine 24x7-Jobs (auf Linux und Windows).

Bei einem Blick in JTOPEN-Forum ist auch keine Hilfe für dieses Problem ist Aussicht gestellt worden. (http://www-912.ibm.com/j_dir/JTOpen.nsf/8178b1c14b1e9b6b8525624f0062fe9f/2125B31CC5EE9C5286256A33005596E7?OpenDocument)

Bei Calls (über stored Procedures) bin ich bisher ohne Timeouts ausgekommen.

Robert P.

BenderD
16-06-06, 11:52
Hallo,

dann wäre es doch eigentlich besser, einen eigenen Wrapper (extends ... DataQueue) zu schreiben und die read Methode zu überschreiben der genau dies kapselt.

mfg

Dieter Bender

PS: oder diesen Toolbox Schmonz durch eine (schmale) Schicht von stored Procedures zu ersetzen, oder vom Design her ganz darauf zu verzichten.


Genau. Prinzipiell funktioniert die Wartezeit bei der Toolbox. Der Wartemechanismus ist aber nur serverseitig implementiert.

Das eigentliche Problem ist aber, dass der DataQueue.read keine Exception wirft, wenn die AS/400 weg ist (und die Javaprogramme auf Windows- bzw. Linux laufen). Der Job bleibt auf warten, auch wenn die AS/400 schon längst wieder da ist und neue Einträge warten.

Daher meine "Hurra ich lebe noch" Kontrolle für meine 24x7-Jobs (auf Linux und Windows).

Bei einem Blick in JTOPEN-Forum ist auch keine Hilfe für dieses Problem ist Aussicht gestellt worden. (http://www-912.ibm.com/j_dir/JTOpen.nsf/8178b1c14b1e9b6b8525624f0062fe9f/2125B31CC5EE9C5286256A33005596E7?OpenDocument)

Bei Calls (über stored Procedures) bin ich bisher ohne Timeouts ausgekommen.

Robert P.