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:
- ja ponownie uruchomić aplikację kliencką
- Kiedy nie skrypt jest wykonywany na zdalnej maszynie przez długi czas
teraz rzeczy, które są mylące mnie są że:
- na zdalnej maszynie, netstat pokazuje port 10175 jest nadal otwarta i słuchania
- 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.
W ostatnim zdaniu "rzeczywistej nazwy hosta" masz na myśli adres IP? Jak zamiast używać nazwy domeny zdalnego używania jego IP? – icl7126
Możesz użyć czegokolwiek. Po prostu nie używaj adresu localhost/loopback –