2014-04-30 15 views
5

Il mio caso d'uso è il seguente. Un'applicazione su una macchina si connette a macchine remote, esegue script su di esse e riporta il risultato. Sto usando Akka Framework per servizi remoti e Play Framework per l'applicazione client. Il codice del server in esecuzione sul mio computer remoto è la seguente:Riconnessione al sistema Akka remoto dopo il riavvio del client

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

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

(appena inizia un'istanza del sistema attore sulla macchina remota)

Ora, quando l'applicazione client vuole eseguire uno script sulla macchina remota, distribuisce un attore su questo sistema remoto che esegue lo script.

Il codice dell'attore che viene distribuito è il seguente:

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

(ottiene i parametri di script, svolge la funzione desiderata, restituisce il risultato)

Sto usando la connessione TCP su SSL per la comunicazione remota . La configurazione è la seguente:

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

Questa configurazione funziona perfettamente ma a volte la macchina remota diventa irraggiungibile. Ho notato che questo accada in due casi:

  1. ho riavviato la mia applicazione client
  2. Quando nessuno script viene eseguito sulla macchina remota per lungo tempo

Ora le cose che mi stanno confondendo sono che:

  1. Sulla macchina remota, netstat mostra porta 10175 è ancora aperta e l'ascolto
  2. Dopo ho riavviato il un'applicazione client e tenta di eseguire l'attore, quando controllo i log della macchina remota, mostra che l'attore è stato eseguito correttamente sulla macchina, ma la risposta non è stata ricevuta dall'applicazione client e quindi ha generato un timeout.

Ho provato ad aggiungere un supervisorStrategy nell'attore client, ma non ha alcun effetto. Sto facendo qualcosa di sbagliato ? Se la connessione TCP è il problema, c'è un modo per terminare la connessione dopo ogni esecuzione? Se il problema è che Actor System si spegne se non viene toccato per un lungo periodo, c'è una configurazione per cambiarlo? Si prega di chiedere se avete bisogno di più codice o informazioni.

Aggiornamento

Quando provo il riavvio del client durante il test sulla mia macchina locale, non dà alcun problema. il server remoto lancia solo i messaggi akka.remote.EndpointAssociationException ma riconnette ed è in grado di inviare risposte. È solo nella modalità di produzione, quando le app vengono distribuite su macchine separate che questo problema si pone. Penso che il mio cliente venga messo in quarantena al riavvio e akka.remote.quarantine-systems-for sia stato rimosso nella nuova versione di Akka.

risposta

3

Ok, ho scoperto il problema. Per chiunque possa affrontare questo problema: Nei file di configurazione delle macchine remote, nella parte netty.ssl della configurazione, ero solito dare i rispettivi nomi degli host mentre li usavo nell'applicazione client per la connessione.Ma nella configurazione dell'applicazione client ho usato per dare il nome host come "localhost" come pensavo non avrei bisogno di questo ovunque.

Ora, controllando i log in modalità di debug, ho scoperto che, quando è stata stabilita la connessione iniziale, l'associazione è stata la seguente:

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

anche se l'app client non era sul localhost di macchine .. Ora questa sessione non ha dato alcun errore. Ma dopo che la connessione si è interrotta (dopo aver riavviato l'applicazione client), e ho provato nuovamente l'esecuzione dello script, ho ottenuto i registri:

2014-05-01 18: 36: 12.045UTC ERRORE [OnCallServer-Akka. actor.default-dispatcher-2] arEndpointWriter - AssociationError [akka.ssl.tcp: //[email protected]: 10175] -> [akka.ssl.tcp: // application @ localhost: 10174]: Errore [Associazione fallita con [akka.ssl.tcp: // application @ localhost: 10174]] [ akka.remote.EndpointAssociationException: associazione fallita con [akka.ssl.tcp: // application @ localhost: 10174] Causato da: akka.remote.transport.netty.NettyTransport $$ anonfun $ socio $ 1 $$ anon $ 2: Connessione rifiutata: localhost/127.0.0.1: 10174

L'app del server per qualche motivo stava tentando di inviare questo messaggio al suo localhost.

La modifica del nome host nella configurazione del client sul nome host effettivo ha risolto il problema.

+0

Nell'ultima frase "hostname effettivo" si intende IP? Come invece di usare il nome di dominio del remoto, usa il suo IP? – icl7126

+0

Puoi usare qualsiasi cosa. Basta non usare l'indirizzo localhost/loopback –

Problemi correlati