PDA

View Full Version : Verbindungsabbruch



KM
14-03-07, 08:40
Hallo,

auf unserem Tomcat-Server läuft ein Servlet, das eine Dataqueue auf der iSeries überwacht und bei jedem Eintrag diverse Werte aus einem Microsoft SQL-Server ermittelt und in eine Ergebnis-Dataqueue schreibt. Dabei wird zu Beginn des Servlets die Verbindung zum SQL-Server und zur iSeries hergestellt. Das funktioniert soweit auch wunderbar.

Jetzt kommt es aber manchmal vor, dass der SQL-Server neu gestartet werden muß. Dadurch erhalte ich dann in meinem Servlet folgende Fehlermeldung und die "Dataqueue-Überwachungsloop" wird natürlich verlassen:

SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]Connection reset by peer: socket write error

Muß ich in so einem Fall dann jedesmal den Tomcat bzw. die Applikation neu starten oder habe ich noch andere Möglichkeiten dies abzufangen bzw. die Verbindung automatisch wieder herzustellen und in der "Überwachungsloop" zu bleiben ?

Gruß,
KM

RobertPic
14-03-07, 21:33
Das klingt mir doch nach nicht behandelter Exception.

Für ein automatische Reconnect gibt es folgende Möglichkeiten (welche ich kenne).

1.) Connections über einen Connectionpool - der kümmert sich meistens um solche Sachen.

2.) Der JDBC-Treiber bietet eine Einstellung wie z.B. der MySQL-JDBC-Treiber. Dort kann man beim Verbinden gleich Reconnect angeben und der macht das von selber.

Beim Microsoft-JDBC-Treiber habe ich das allerdings nicht gesehen, hier kann man einen Failover-Listener anmelden...auch ehere mühsam.

3.) Eine entsprechende Exceptionabfrage inkl. eine Wiederhol ungs- und/oder Reconnect-Logik. Wichtig sind hier auch Fehlerzähler und Wartezeiten, damit das ganze nicht beim Warten 100% CPU braucht.
Anmerkung: Wenn der Service für Onlineprogramme ist, schaut die Strategie etwas anders aus: nur 1 Reconnect und bei Fehler eine Fehlermeldung als Anwort.

Meiner Meinung nach kommst du um 3. sowieso nicht herum. Auch wenn das Reconnect automatisch funktioniert, fliegt das Programm trotzdem noch, wenn genau eine Abfrage ist, wenn der SQL-Server mal nicht da ist.

KM
15-03-07, 05:50
Hallo Robert,

danke für Deine Tips. Ich habe mir jetzt folgendermaßen beholfen. Ich weiß jetzt zwar nicht wie "elegant" das ist, aber es funktioniert zumindest. Vor dem Zugriff auf den SQL-Server führe ich folgendes aus:


if (validateConnection(sq_conn) == false) {
// Verbindung zur SQL-Datenbank aufbauen
String sq_driver = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
String sq_url = "jdbc:microsoft:sqlserver://" + sq_server + ":1433;databaseName=" + sq_database;
Class.forName(sq_driver);
sq_conn = DriverManager.getConnection(sq_url, sq_user, sq_pwd);

// Statement-Objekte erzeugen
sq_stmt_table = sq_conn.createStatement();
sq_stmt_in = sq_conn.createStatement();
sq_stmt_out = sq_conn.createStatement();
sq_stmt = sq_conn.createStatement();
}

//
// Prüfen, ob die Verbindung zum SQL-Server besteht
//
public static boolean validateConnection(Connection sq_conn) {

try{
sq_conn.getMetaData();
}

catch(Exception e) {
return false;
}
return true;
}

Die Sache mit den Connection Pools müsste ich mir auch mal genauer anschauen. Hab auch gelesen, dass es damit funktionieren müsste. Hab aber auf die Schnelle kein Beispiel gefunden wie ich das bei mir einbauen müsste.

Gruß,
KM

BenderD
16-03-07, 07:28
Hallo,

hier findest du einen Connection Pool:
Overview - Commons DBCP (http://jakarta.apache.org/commons/dbcp/)
Beispiele zur Einbindung sind entweder bei Apache, oder über google sicher zu finden und wenn man das ohne JNDI, DataSource und jedes Gedöns macht, dann hat man das recht schnell erledigt. Solltest du auf Probleme stoßen, ich habe da sicher auch irgendwo ein Beispiel und wenn ich mal Lust zum kramen habe...

mfg

Dieter Bender


Hallo Robert,

danke für Deine Tips. Ich habe mir jetzt folgendermaßen beholfen. Ich weiß jetzt zwar nicht wie "elegant" das ist, aber es funktioniert zumindest. Vor dem Zugriff auf den SQL-Server führe ich folgendes aus:


if (validateConnection(sq_conn) == false) {
// Verbindung zur SQL-Datenbank aufbauen
String sq_driver = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
String sq_url = "jdbc:microsoft:sqlserver://" + sq_server + ":1433;databaseName=" + sq_database;
Class.forName(sq_driver);
sq_conn = DriverManager.getConnection(sq_url, sq_user, sq_pwd);

// Statement-Objekte erzeugen
sq_stmt_table = sq_conn.createStatement();
sq_stmt_in = sq_conn.createStatement();
sq_stmt_out = sq_conn.createStatement();
sq_stmt = sq_conn.createStatement();
}

//
// Prüfen, ob die Verbindung zum SQL-Server besteht
//
public static boolean validateConnection(Connection sq_conn) {

try{
sq_conn.getMetaData();
}

catch(Exception e) {
return false;
}
return true;
}

Die Sache mit den Connection Pools müsste ich mir auch mal genauer anschauen. Hab auch gelesen, dass es damit funktionieren müsste. Hab aber auf die Schnelle kein Beispiel gefunden wie ich das bei mir einbauen müsste.

Gruß,
KM

KM
16-03-07, 08:12
Danke, das werde ich mir bei Gelegenheit mal anschauen.

Ich habe auch gesehen, dass es z.B. bei MySQL den Parameter "autoReconnect" gibt. Beim MSSQLServer gibt's den aber nicht.

Außerdem brauche ich in meiner jetzigen Applikation nicht mehrere Verbindungen, sondern ich brauche nur dann eine neue Verbindung, wenn der SQL-Server neu gestartet wird. Dafür reicht mir erstmal meine jetzige Lösung.

Gruß,
KM

BenderD
16-03-07, 08:19
Hallo,

ein ConnectionPool kann auch die Größe 1 haben und macht mehr als nur Connections aus einem Pool rausgeben (je nach Implementierung). Auf diesem Weg wird das gesamte Connection Handling zentralisiert und Standard Anforderungen (wie validate, timeout etc.) werden durch eine Standard Komponente abgefackelt (die meist besser und komfortabler ist als eigene Handarbeit).
Das ist ja der immense Unterschied zwischen RPG und Java, dass es bei Java Unmengen von verwendbaren Komponenten höchster Qualität gibt, da sollte man seine Arbeitsweise drauf einstellen und sich ein wenig abgewöhnen alles selber machen zu wollen.

Dieter Bender


Danke, das werde ich mir bei Gelegenheit mal anschauen.

Ich habe auch gesehen, dass es z.B. bei MySQL den Parameter "autoReconnect" gibt. Beim MSSQLServer gibt's den aber nicht.

Außerdem brauche ich in meiner jetzigen Applikation nicht mehrere Verbindungen, sondern ich brauche nur dann eine neue Verbindung, wenn der SQL-Server neu gestartet wird. Dafür reicht mir erstmal meine jetzige Lösung.

Gruß,
KM