2014-04-30 39 views
5

Mój przypadek użycia jest następujący. Aplikacja na komputerze łączy się ze zdalnymi komputerami, wykonuje na nich skrypty i przywraca wynik. Używam programu Akka Framework do zdalnych i Play Framework dla aplikacji klienckiej. Kod serwera uruchomionego na moim komputerze zdalnym jest następujący:Ponowne podłączenie do zdalnego systemu Akka po ponownym uruchomieniu klienta

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

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

(tylko uruchamia instancję systemu aktora na komputerze zdalnym)

Teraz, gdy aplikacja klient chce uruchomić skrypt na zdalnym komputerze, uruchamia aktora na tym zdalnym systemie, który wykonuje skrypt.

Kod aktora, który zostanie wdrożony jest w następujący sposób:

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()); 
      } 
     } 
    } 
} 

(wstaje parametry skryptu, wykonuje żądaną funkcję, zwraca wynik)

używam połączenia TCP przez SSL dla usług zdalnych . Konfiguracja jest następująca:

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 = "" 
     } 
    } 

Ta konfiguracja działa idealnie, ale czasami zdalna maszyna staje się nieosiągalna. Zauważyłem to dzieje się w dwóch przypadkach:

  1. ja ponownie uruchomić aplikację kliencką
  2. Kiedy nie skrypt jest wykonywany na zdalnej maszynie przez długi czas

teraz rzeczy, które są mylące mnie są że:

  1. na zdalnej maszynie, netstat pokazuje port 10175 jest nadal otwarta i słuchania
  2. Po zrestartuj Aplikacja kliencka i spróbuj wykonać aktora, kiedy sprawdzam dzienniki zdalnej maszyny, pokazuje, że aktor został pomyślnie wykonany na komputerze, ale odpowiedź nie została odebrana przez moją aplikację kliencką, a tym samym spowodowała przekroczenie limitu czasu.

Próbowałem dodanie supervisorStrategy w aktora klienta, ale to nie ma żadnego wpływu. Czy robię coś źle ? Jeśli problemem jest połączenie TCP, czy istnieje sposób na zakończenie połączenia po każdym wykonaniu? Jeśli problem polega na tym, że Actor System wyłącza się, jeśli nie jest dotykany przez długi czas, czy istnieje konfiguracja, aby to zmienić? Zapytaj, czy potrzebujesz więcej kodu lub informacji.

Aktualizacja

Przy próbie ponownego uruchomienia klienta podczas testowania na moim komputerze lokalnym, to nie daje żadnego problemu. serwer zdalny po prostu wyrzuca wiadomości akka.remote.EndpointAssociationException, ale ponownie łączy się i jest w stanie wysyłać odpowiedzi. Tylko w trybie produkcyjnym, gdy aplikacje są wdrażane na oddzielnych komputerach, pojawia się ten problem. Myślę, że mój klient jest poddawany kwarantannie po ponownym uruchomieniu, a akka.remote.quarantine-systems-for została usunięta w nowej wersji Akka.

Odpowiedz

3

Ok, dowiedziałem się o problemie. Dla każdego, kto może stanąć przed tym problemem: W plikach konfiguracyjnych komputerów zdalnych, w części netty.ssl konfiguracji, użyłem ich nazw hostów, ponieważ użyłem tego w aplikacji klienckiej do połączenia.Jednak w konfiguracji aplikacji klienckiej użyłem nazwy hosta jako "localhost", ponieważ myślałem, że nigdzie jej nie potrzebuję.

Teraz sprawdzenie logów w trybie debugowania, I okazało się, że gdy początkowe połączenie zostało nawiązane, stowarzyszenie zostało w następujący sposób:

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

mimo że aplikacja kliencka nie znajdowała się na komputerze localhost .. Ta sesja nie dała żadnych błędów. Ale po tym jak połączenie zostało utracone (po ponownym uruchomieniu aplikacji klienckiej) i próbowałem ponownego wykonywania skryptu, mam kłody:

2014-05-01 18: 36: 12.045UTC ERROR [OnCallServer-Akka. actor.default-dispatcher-2] arEndpointWriter - AssociationError [akka.ssl.tcp: //[email protected]: 10175] -> [akka.ssl.tcp: // application @ localhost: 10174]: Błąd [Association nie powiodło się z [akka.ssl.tcp: // application @ localhost: 10174]] [ akka.remote.EndpointAssociationException: Association failed with [akka.ssl.tcp: // application @ localhost: 10174] Przyczyna: akka.remote.transport.netty.NettyTransport $$ anonfun $ associate $ 1 $$ anon $ 2: Połączenie odrzucone: localhost/127.0.0.1: 10174

Aplikacja serwera z jakiegoś powodu próbowała wysłać tę wiadomość z powrotem do lokalnego hosta.

Zmiana nazwy hosta w konfiguracji klienta na rzeczywistą nazwę hosta rozwiązała problem.

+0

W ostatnim zdaniu "rzeczywistej nazwy hosta" masz na myśli adres IP? Jak zamiast używać nazwy domeny zdalnego używania jego IP? – icl7126

+0

Możesz użyć czegokolwiek. Po prostu nie używaj adresu localhost/loopback –

Powiązane problemy