2014-04-30 5 views
5

Mein Anwendungsfall ist folgender. Eine Anwendung auf einem Computer stellt eine Verbindung zu Remote-Computern her, führt Skripts für sie aus und bringt das Ergebnis zurück. Ich verwende Akka Framework für Remoting und Play Framework für die Client-Anwendung. Der Code des Servers, auf meinem Remote-Computer ausgeführt wird, wie folgt:Erneutes Verbinden mit dem Remote-Akka-System nach dem Neustart des Clients

public static void main(String[] args) 
{ 
    OnCallServer app = new OnCallServer(); 
    app.executeServer(); 
} 

private void executeServer() { 
    ActorSystem system = ActorSystem.create("OnCallServer"); 
} 

(gerade startet eine Instanz des Darstellers System auf dem entfernten Rechner)

Nun, wenn die Client-Anwendung möchte ein Skript ausführen Auf dem Remote-Computer wird ein Akteur auf diesem Remote-System implementiert, der das Skript ausführt.

Der Code des Darstellers, der eingesetzt wird ist wie folgt:

public static class RemoteActor extends UntypedActor implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Override 
    public void onReceive(Object message) throws Exception { 
     Config config = context().system().settings().config(); 
     String host = config.getConfig("akka.remote.netty.ssl").getString("machineName"); 
     String sysDesc = host; 
     if (message instanceof ScriptExecutionParams) { 
      System.out.println("scriptParam"); 
      ScriptExecutionParams scriptParams = (ScriptExecutionParams) message; 

      if (scriptParams.function == ScriptFunction.EXECUTE) { 
       getSender().tell(executeScript(scriptParams.getName(), scriptParams.getArgument(), sysDesc), getSelf()); 
      } else if (scriptParams.function == ScriptFunction.DEPLOY) { 
       getSender().tell(deployScript(scriptParams.getName(), scriptParams.getContent(), sysDesc), getSelf()); 
      } else if (scriptParams.function == ScriptFunction.REMOVE) { 
       getSender().tell(removeScript(scriptParams.getName(), sysDesc), getSelf()); 
      } 
     } 
    } 
} 

(wird Skriptparametern führt die gewünschte Funktion, gibt das Ergebnis)

Ich verwende TCP-Verbindung über SSL für remoting . Die Konfiguration ist wie folgt:

remote { 
     enabled-transports = ["akka.remote.netty.ssl"] 
     netty.ssl { 
      hostname = "localhost" (for client) and hostname (for remote servers) 
      port = 10174 (for client) and 10175 (for server) 
      enable-ssl = true 
     } 
     netty.ssl.security { 
      key-store = "clientKeystore.jks" 
      trust-store = "clientTruststore.jks" 
      key-store-password = "xxx" 
      key-password = "xxx" 
      trust-store-password = "xxx" 
      protocol = "SSLv3" 
      enabled-algorithms = [SSL_RSA_WITH_NULL_SHA] 
      random-number-generator = "" 
     } 
    } 

Diese Einrichtung funktioniert einwandfrei, aber manchmal wird die Remote-Maschine unerreichbar. Ich habe dies geschieht in zwei Fällen bemerkt:

  1. ich neu starten, meine Client-Anwendung
  2. Wenn kein Skript für eine lange Zeit

die Dinge nun auf dem entfernten Rechner ausgeführt, die mich verwirren sind dass:

  1. Auf dem Remote-Rechner, zeigt netstat Port 10175 ist noch offen und hören
  2. Nachdem ich den Neustart Client-Anwendung und versuchen, den Akteur auszuführen, wenn ich die Protokolle der Remote-Maschine überprüfe, zeigt es, dass der Akteur erfolgreich auf der Maschine ausgeführt wurde, aber die Antwort wurde nicht von meiner Client-Anwendung erhalten und führte daher zu einem Timeout.

Ich habe versucht, eine SupervisorStrategy in der Client-Akteur hinzufügen, aber es hat keine Auswirkungen. Mache ich etwas falsch ? Wenn die TCP-Verbindung das Problem ist, gibt es eine Möglichkeit, die Verbindung nach jeder Ausführung zu beenden? Wenn das Problem darin besteht, dass das Actor-System herunterfährt, wenn es lange nicht berührt wird, gibt es eine Konfiguration, um dies zu ändern? Bitte fragen Sie, ob Sie mehr Code oder Informationen benötigen.

aktualisiert

Wenn ich den Client versuchen, neu zu starten, wenn auf meinem lokalen Rechner zu testen, gibt kein Problem. Der Remote-Server löst nur akka.remote.EndpointAssociationException-Nachrichten aus, verbindet sich jedoch erneut und kann Antworten senden. Es ist nur im Produktionsmodus, wenn die Apps auf separaten Computern bereitgestellt werden, tritt dieses Problem auf. Ich denke, dass mein Client beim Neustart unter Quarantäne gestellt wird und akka.remote.quarantine-systems-for in der neuen Akka-Version entfernt wurde.

Antwort

3

Ok, ich habe das Problem herausgefunden. Für alle anderen, die dieses Problem haben könnten: In den Konfigurationsdateien der Remote-Computer, im Netty.ssl-Teil der Konfiguration, habe ich ihre jeweiligen Hostnamen angegeben, wie ich sie in der Client-Anwendung für die Verbindung verwendet habe.Aber in der Konfiguration der Client-Anwendung habe ich den Hostnamen als "localhost" angegeben, da ich dachte, ich würde das nirgendwo brauchen.

nun die Protokolle im Debug-Modus überprüft, fand ich heraus, dass, wenn die anfängliche Verbindung hergestellt wurde, wurde der Verein wie folgt:

2014-05-01 18: 35: 38.503UTC DEBUG [OnCallServer -akka.actor.default-dispatcher-3] Remoting - Zugehörig [akka.ssl.tcp: //[email protected]: 10175] < - [akka.ssl.tcp: // Anwendung @ localhost: 10174]

obwohl die Client-App nicht auf den Maschinen localhost war .. Nun gab diese Sitzung keine Fehler. Aber nachdem die Verbindung unterbrochen wurde (nach der Client-Anwendung neu starten), und ich versuchte, erneut das Skript ausgeführt wird, habe ich die Protokolle:

2014-05-01 18: 36: 12.045UTC ERROR [OnCallServer-akka. actor.default-dispatcher-2] arEndpointWriter - Assoziationsfehler [akka.ssl.tcp: //[email protected]: 10175] -> [akka.ssl.tcp: // application @ localhost: 10174]: Fehler [Verbindung fehlgeschlagen mit [akka.ssl.tcp: // application @ localhost: 10174]] [ akka.remote.EndpointAssociationException: Verbindung fehlgeschlagen mit [akka.ssl.tcp: // application @ localhost: 10174] verursacht durch: akka.remote.transport.netty.NettyTransport $$ anonfun $ associate $ 1 $$ anon $ 2: Verbindung verweigert: localhost/127.0.0.1: 10174

Die Server-App versuchte aus irgendeinem Grund, diese Nachricht an ihren lokalen Host zu senden.

Das Ändern des Hostnamens in der Client-Konfiguration zum tatsächlichen Hostnamen löste das Problem.

+0

Im letzten Satz von 'tatsächlichen Hostnamen' meinst du IP? Wie anstelle von Domain-Namen der Fernbedienung verwenden Sie ihre IP? – icl7126

+0

Sie können alles verwenden. Verwenden Sie keine Localhost/Loopback-Adresse –

Verwandte Themen