重新启动客户端后重新连接到远程Akka系统

Adi*_*ade 6 java akka

我的用例如下.计算机上的应用程序连接到远程计算机,在其上执行脚本并返回结果.我正在使用Akka Framework进行远程处理,并为客户端应用程序使用Play Framework.在我的远程机器上运行的服务器的代码如下:

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

private void executeServer() {
    ActorSystem system = ActorSystem.create("OnCallServer");
}
Run Code Online (Sandbox Code Playgroud)

(只是在远程机器上启动actor系统的一个实例)

现在,当客户端应用程序想要在远程计算机上运行脚本时,它会在此远程系统上部署一个执行该脚本的actor.

部署的actor的代码如下:

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());
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

(获取脚本参数,执行所需的功能,返回结果)

我正在使用SSL上的TCP连接进行远程处理.配置如下:

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 = ""
        }
    }
Run Code Online (Sandbox Code Playgroud)

此设置工作正常,但有时远程机器无法访问.我注意到这种情况发生在两种情况:

  1. 我重启我的客户端应用程序
  2. 长时间没有在远程计算机上执行脚本时

现在令我困惑的是:

  1. 在远程计算机上,netstat显示端口10175仍处于打开和监听状态
  2. 在我重新启动客户端应用程序并尝试执行actor之后,当我检查远程计算机的日志时,它显示该actor已在计算机上成功执行,但我的客户端应用程序未收到响应,因此导致超时.

我尝试在客户端actor中添加supervisorStrategy,但它没有任何效果.难道我做错了什么 ?如果TCP连接是问题,有没有办法在每次执行后终止连接?如果问题是如果长时间未触摸Actor系统关闭,是否有配置更改此设置?请询问您是否需要更多代码或信息.

更新

当我在本地计算机上进行测试时尝试重新启动客户端时,它不会产生任何问题.远程服务器只是抛出akka.remote.EndpointAssociationException消息但重新连接并能够发送回复.只有在生产模式下,当应用程序部署在不同的计算机上时才会出现此问题.我认为我的客户端在重新启动时被隔离,并且在新的Akka版本中删除了akka.remote.quarantine-systems-for.

Adi*_*ade 3

好吧,我发现了问题。对于可能面临此问题的其他人:在远程计算机的配置文件中,在配置的 netty.ssl 部分中,我曾经给出它们各自的主机名,因为我在客户端应用程序中使用它进行连接。但在客户端应用程序配置中,我曾经将主机名指定为“localhost”,因为我认为我在任何地方都不需要它。

现在,在DEBUG模式下查看日志,发现初始连接建立时,关联如下:

2014-05-01 18:35:38.503UTC 调试 [OnCallServer-akka.actor.default-dispatcher-3] 远程处理 - 关联 [akka.ssl.tcp://OnCallServer@sp-cms-backend4.nm.flipkart.com :10175] <- [akka.ssl.tcp://application@localhost:10174]

即使客户端应用程序不在本地主机上。现在此会话没有给出任何错误。但是在连接丢失后(重新启动客户端应用程序后),并且我尝试重新执行脚本,我得到了日志:

2014-05-01 18:36:12.045UTC 错误 [OnCallServer-akka.actor.default-dispatcher-2] arEndpointWriter - AssociationError [akka.ssl.tcp://OnCallServer@sp-cms-backend4.nm.flipkart.com :10175] -> [akka.ssl.tcp://application@localhost:10174]: 错误 [关联失败 [akka.ssl.tcp://application@localhost:10174]] [ akka.remote.EndpointAssociationException: 关联[akka.ssl.tcp://application@localhost:10174] 失败原因:akka.remote.transport.netty.NettyTransport$$anonfun$associate$1$$anon$2:连接被拒绝:localhost/127.0.0.1:10174

服务器应用程序出于某种原因尝试将此消息发送回其本地主机。

将客户端配置中的主机名更改为实际主机名解决了问题。