Reconnect-Feature

Added by achristian about 1 year ago

Noctarius:

Hiho

Sag mal gibt es in SIMON eigentlich die Möglichkeit eine abgebrochene Verbindung wieder aufzubauen ohne alle Bindings erneut zu beziehen?

Gruß Chris

PS: Ich hab noch kleinere Bugfixes für das Interface Lookup, kommen die Tage im Forum bzw Bugtracker.

achristian:

Nein. Du musst erneut einen Lookup machen. Bisher gibt es da keine(n) Hilfe/Automatismus von SIMON.
Mit einfachen Remote-Objekten die ein Client sich via Lookup geholt hat mag ein automatischer Reconnect noch einfach zu machen sein.

Aber was ist mit impliziten Remote-Objekten (Callbacks). Wenn der Server dem Client nach dem "login" ein Session-Remote-Objekt mitgibt, und die Verbindung unterbrochen wird, ist es nicht so easy diese Verbindung mitsamt dem daran hängenden Zustand wieder herzustellen.

Ich werde da mal drüber nachdenken ob und wie man das in SIMON bewerkstelligen könnte.

Danke für den Hinweis ..

Gruß
Alex

Noctarius:

Automatisch wäre es gar nicht nötig. Mit dem ClosedListener und einem expliziten lookup.reconnect() wäre es ja ok.

achristian:

Hmm. Für Remote-Objekte erster Instanz wäre das ohne großes Problem machbar. Aber für Remote-Objekte die man nicht mittels eines lookups holen kann, sondern nur durch aufruf einer Remote-Methode ist das wohl recht aufwendig. Dummerweise wird in SIMON nicht wirklich zwischen diesen beiden Remote-Objekt-Arten unterschieden.

- Alex

Noctarius:

Wir können die Diskussion ja mal ins SIMIN Forum verlagern :) Wäre es nicht möglich alle Remote-Objekte in ner HashMap samt passendem Hash zu speichern und mit einem Timeout zu versehen?


Replies (7)

RE: Reconnect-Feature - Added by achristian about 1 year ago

Doch, schon. Problem sind aber nach wie vor die Callbacks.

Callback-Objekte werden implizit zu Remote-Objekten sobald sie die Netzwerkverbindung überqueren. Mit dem Unreferenced Interface kann man aber auf Verbindungsverluste reagieren. Gerade beim Session-Pattern (Siehe Wiki) ist das wichtig. Wenn man nun auch die Callback-Objekte reconnecten möchte, dann müsste SIMON das auslösen von "unreferenced" unterdrücken. Das geht aber nur, wenn der Server weiß dass er's unterdrücken muss. Und das geht nur, wenn man mit dem Server gesprochen hat. Da die Verbindung ja aber in diesem Moment unterbrochen ist, geht das nicht. Als Workaround könnte der Server ein Timeout benutzen. Läuft dieses Timeout aus, so ist die Verbindung wirklich tot. Kommt jedoch der erneute Verbindungsaufbau innerhalb der Timeout-Zeit, könnte man alles wieder anschließen. Aber man müsste hier dann irgend einen Sicherheitsmechanismus einbauen. Denn der erneute Reconnect hätte dann ja keinen Loginaufruf getätigt und der Client wäre einfach so "authentifiziert" und hätte Zugriff auf das Session-Objekt.

Hinzu kommt, dass die SIMON Architektur das (noch) nicht vorsieht und es mit viel Aufwand verbunden wäre. Ich bin mir auch nicht sicher ob man das ganze überhaupt "sicher" hinbekommt.
Wenn man sich aber nur auf die First-Level Remote-Objekte (also die, an die man mittels normalen Lookup ran kommt) in Bezug auf den Reconnect beschränkt, wäre das wohl einfach umzusetzen und auch als "sicher" anzusehen.

Wobei dann noch die Frage ist: Worin liegt dann der Vorteil von

1// Im ClosedListener
2lookup.reconnect();

zu

1// Im ClosedListener
2lookup.lookup("myObject");

??

- Alex

RE: Reconnect-Feature - Added by Noctarius about 1 year ago

Natürlich bringt es nur einen Vorteil, wenn aktuell existierende Objekte wieder verknüpft werden. Man könnte um programatisch darauf zu reagieren (es könnten ja eventuell Services oder ähnliches unreferenced sein) z.b. den Listener um eine Methode "reconnected" einbauen.

Wenn es möglich ist würde ich einstellbar machen ob der reconnect automatisch gestartet werden soll oder ob dieser im Source selber durchgeführt werden soll, z.B. um noch irgendwas aufzuräumen oder vorübergehend Anfragen zu pausieren.

Mein aktuelles Problem (vielleicht hast du ja eine bessere Idee):

          |--- IP 1 --- |
Webchat - |             | - Openfire
          |--- IP 2 ----| 

Ich habe von einem Server (Webchat) zu einem anderen Server (Openfire XMPP Server) 2 Verbindungen offen (über je eine externe IP). Da beide Leitungen eine DSL Verbindung darstellen kann jederzeit eine von beiden Leitungen abbrechen. Die beiden Leitungen bilden dabei eine Art Failover und gleichzeitig eine Lastverteilung wenn beide verfügbar sind.

Innerhalb der Server werden multiple Verbindungen automatisch verwaltet, aber ich muss gewisse Objekte über jede Verbindung abfragen (auch wenn es sich theoretisch um die selbe Instanz handelt, die Proxies sind ja unterschiedlich). Beim Verbindungabbruch muss entsprechend abgeräumt und neu connected werden. Dabei wird beim Connect die Methode login(ManagerAdvisor) aufgerufen und der neue Advisor registiert. Es wäre halt schön, wenn die alte Instanz automatisch wiederhergestellt werden könnte. Es handelt sich hierbei definitiv um ein Callback Objekt.

Die Frage ist doch, kann man jedem Objekt nicht eine eindeutige ID zuweisen (innerhalb des Lookup wird sowas ähnliches ja mit den Hashes schon gemacht) und bei einem Reconnect werden die aktuell als unreferenced deklarierten Objekte anhand ihrer Unique ID wieder abgerufen. Dazu müssten halt beide Seiten diese ID kennen.

RE: Reconnect-Feature - Added by achristian about 1 year ago

Noctarius wrote:

Natürlich bringt es nur einen Vorteil, wenn aktuell existierende Objekte wieder verknüpft werden.

Genau das passiert doch auch bei einem lookup ... Nur geht das eben nur für Nicht-Callback-Objekte.

Man könnte um programatisch darauf zu reagieren (es könnten ja eventuell Services oder ähnliches unreferenced sein) z.b. den Listener um eine Methode "reconnected" einbauen.

Ja, das wäre ohne weiteres machbar. Nur wird zuerst ein "unreferenced" ausgelöst werden und ggf. kommt dann noch nach Zeitfenster X ein "reconnected". Jetzt ist halt die Frage: Wie unterscheidet man eine für immer getrennte Verbindung (eigentlich signalisiert durch "unreferenced") von einer Reconnect-Verbindung (dann signalisiert dich "reconnected")?

Meine obige Idee mit dem Timeout gefällt mir noch nicht so.

Wenn es möglich ist würde ich einstellbar machen ob der reconnect automatisch gestartet werden soll oder ob dieser im Source selber durchgeführt werden soll, z.B. um noch irgendwas aufzuräumen oder vorübergehend Anfragen zu pausieren.

Sollte nicht das Problem darstellen.

Mein aktuelles Problem (vielleicht hast du ja eine bessere Idee):

[...]

Ich habe von einem Server (Webchat) zu einem anderen Server (Openfire XMPP Server) 2 Verbindungen offen (über je eine externe IP). Da beide Leitungen eine DSL Verbindung darstellen kann jederzeit eine von beiden Leitungen abbrechen. Die beiden Leitungen bilden dabei eine Art Failover und gleichzeitig eine Lastverteilung wenn beide verfügbar sind.

Innerhalb der Server werden multiple Verbindungen automatisch verwaltet, aber ich muss gewisse Objekte über jede Verbindung abfragen (auch wenn es sich theoretisch um die selbe Instanz handelt, die Proxies sind ja unterschiedlich). Beim Verbindungabbruch muss entsprechend abgeräumt und neu connected werden. Dabei wird beim Connect die Methode login(ManagerAdvisor) aufgerufen und der neue Advisor registiert. Es wäre halt schön, wenn die alte Instanz automatisch wiederhergestellt werden könnte. Es handelt sich hierbei definitiv um ein Callback Objekt.

Die Frage ist doch, kann man jedem Objekt nicht eine eindeutige ID zuweisen (innerhalb des Lookup wird sowas ähnliches ja mit den Hashes schon gemacht) und bei einem Reconnect werden die aktuell als unreferenced deklarierten Objekte anhand ihrer Unique ID wieder abgerufen. Dazu müssten halt beide Seiten diese ID kennen.

Hmm, das ließe sich ja auch oberhalb von SIMON lösen. Du müsstest nur deine Schnittstelle etwas erweitern, so dass du wieder in den zuletzt gültigen Zustand kommst. Aber ich geb dir Recht: Wenn SIMON das von Haus aus könnte, wäre es einfacher.
Das mit der ID ließe sich machen. Wenn der Server ein Callbackobjekt als Antwort zurück an den Client schickt, wird beim internen registrieren des Objekts als "RemoteObjekt" eh eine Art ID erzeugt. Der Client bekommt die, zusammen mit dem Interface das dieses Callback-Objekt beschreibt zugeschickt. Dieser verwendet die ID um Methodenaufrufe zu genau dieser Callback-Instanz zu schicken.
Ohne das im Code nochmal nachgeforscht zu haben würde ich mal behaupten, ich müsste "nur" folgendes tun:

  • Beim Lookup mit Angeben ob das eine Verbindung ist die "auto-reconnect" beherrscht oder nicht. Damit weiß der Server ob er "unreferenced" für "timout"-Zeit unterdrücken muss um auf einen eventuellen Reconnect zu warten
  • Der Client muss bei Verbindungsabbruch dann lediglich die Netzwerk-Session wieder aufbauen. Hierzu müsste er eine "Reconnect" Message an den Server schicken. Diese Message müsste die IDs alle Callback-Objekte beinhalten die der Client kennt. Der Server kann dann lokal die neue Netzwerk-Session den Objekten zuordnen.
  • Die Nicht-Callback-Objekte muss der Client ebenfalls mit der neuen Netzwerk-Session versehen.

Hmm. Klingt nach ein wenig Arbeit. "Könnte" aber funktionieren. Ich muss nur nochmal schauen wie die IDs aufgebaut sind/werden.

- Alex

RE: Reconnect-Feature - Added by Noctarius about 1 year ago

Klingt jetzt spontan so als müsste es funktionieren. Die Idee vorher zu definieren ob eine Verbindung auto-reconnect unterstützen soll ist super.

Als alternativer Vorschlag kommt mir grad die Idee, generell eine Art Multipath einzubauen. Also statt einer IP könnte man mehrere IPs beim Lookup angeben und alle Verbindungen werden parallel aufgebaut.
Dann hätte man nur den Sonderfall wenn beide Verbindungen gleichzeitig abbrechen, weil z.B. ein Server komplett abraucht oder ähnliches.

RE: Reconnect-Feature - Added by achristian about 1 year ago

Hab mal in den Code geschaut und überlegt... Könnte funktionieren. Ich muss die Sache mit der ID etwas abändern. Die wird zur Zeit gebildet aus:

 1
 2sb.append("[");
 3        sb.append(remoteObject.getClass().getName());
 4        sb.append("|ip=");
 5        sb.append(IP);
 6        sb.append(";sessionID=");
 7        sb.append(sessionId);
 8        sb.append(";remoteObjectHash=");
 9        sb.append(remoteObject.hashCode());
10        sb.append("]");

Die Session-ID ist hier die ID der MINA-Netzwerksession. Hatte mich für diese ID entschieden um später noch sicherstellen zu können dass ein Client mit ID1 kein Session-Remote-Objekt vom Client mit der ID2 benutzt. Werde das wohl um eine weitere ID oder Hash erweitern, so dass ich die SessionID austauschen kann, ohne die zuordnung zum Client zu verlieren. Der Server, der diese ID vergibt, kann ja einen Random-Hash nehmen oder so.

Auf beiden Seiten muss ich dann nur noch eine Liste einbauen in die alle Objekte eines bestimmten Client-Server-Hashs kommen und die, bei einem reconnect eine neue Session zugeordnet bekommen müssen.

Puuh, wird doch eine recht große Änderung. Sollte aber machbar sein. Mal schauen ob ich dafür Version 1.2.0 noch nehme, oder ob ich da einen Major-Versions-Sprung nehme und auf 2.0.0 gehe.

Bzgl. des Multipaths: Denke das geht noch einfacher: Vor dem Lookup muss man einfach zwei Netzwerkverbindungen konfigurieren. Beim Lookup werden dann zwei Verbindungen aufgebaut und den Objekten einfach 2 Netzwerk-Sessions gegeben. Entweder dient dann Session1 als Master und Session2 als Fallback, oder man man ein RoundRobin für die Sessions um die Last zu verteilen. Weiß allerdings noch nicht wie der Server darauf regieren würde wenn Aurruf1 von der einen Session kommt, und Aufruf2 von einer anderen. Müsste ggf. von "Zuordnung auf basis von Sessions" durch "Zuordnung auf Basis von Hash-Codes" umstellen. Aber das wäre dann definitiv einen Major-versionssprung wert.

- Alex

RE: Reconnect-Feature - Added by Noctarius about 1 year ago

Als ID könntest du auch die Klasse UUID nutzen :)

RE: Reconnect-Feature - Added by achristian about 1 year ago

Stimmt. Die Klasse wollte ich eh schon lange mal für was sinnvolles nutzen :-)

(1-7/7)