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

时间:2014-04-30 12:40:25

标签: 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");
}

(只是在远程机器上启动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());
            }
        }
    }
}

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

我正在使用基于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 = ""
        }
    }

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

  1. 我重启了我的客户端应用程序
  2. 长时间没有在远程计算机上执行脚本
  3. 现在令我困惑的是:

    1. 在远程计算机上,netstat显示端口10175仍处于打开状态并正在侦听
    2. 在我重新启动客户端应用程序并尝试执行actor之后,当我检查远程计算机的日志时,它显示该actor已在计算机上成功执行,但我的客户端应用程序未收到响应,因此导致超时。
    3. 我尝试在客户端actor中添加supervisorStrategy,但它没有任何效果。难道我做错了什么 ?如果TCP连接是问题,有没有办法在每次执行后终止连接?如果问题是如果长时间未触摸Actor系统关闭,是否有配置更改此设置?请询问您是否需要更多代码或信息。

      更新

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

1 个答案:

答案 0 :(得分:3)

好的,我发现了问题。对于其他可能遇到此问题的人: 在远程机器的配置文件中,在配置的netty.ssl部分,我曾经在客户端应用程序中使用它来提供它们各自的主机名以进行连接。但是在客户端应用程序配置中,我曾经将主机名命名为" localhost"因为我以为我不需要这个。

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

  

2014-05-01 18:35:38.503UTC DEBUG [OnCallServer-akka.actor.default-dispatcher-3] Remoting - Associated [akka.ssl.tcp://OnCallServer@sp-cms-backend4.nm。 flipkart.com:10175]< - [akka.ssl.tcp:// application @ localhost:10174]

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

  

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

服务器应用程序出于某种原因试图将此消息发回给它的本地主机。

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