有没有一种有效的方法来测试RMI服务器是否已启动?

时间:2013-12-18 18:12:54

标签: java rmi

我有一个RMI客户端测试RMI服务器是否正在运行且可访问

此刻,我每隔几秒就进行一次测试:

try {
    rMIinstance.ping();
} catch (RemoteException e) {
    getInstanceRegister().removeInstance(rMIinstance);
}

ping()是一个简单的虚拟RMI调用。)

如果实例离线,我大约1分钟后得到

  

java.net.ConnectException: Connection timed out

异常,显示服务器处于脱机状态。

然而,代码挂了一分钟,这对我们来说远远不够。 (我不想更改超时设置。) 是否有更快的方法来执行此测试?

4 个答案:

答案 0 :(得分:2)

您可以从计时器中断线程。它有点hacky并将抛出InterruptedException而不是RemoteException,但它应该工作。

try {
    Timer timer = new Timer(true);
    TimerTask interruptTimerTask = new InterruptTimerTask(Thread.currentThread());
    timer.schedule(interruptTimerTask, howLongDoYouWantToWait);
    rMIinstance.ping();
    timer.cancel();
} catch (RemoteException | InterruptedException e) {
    getInstanceRegister().removeInstance(rMIinstance);
}

TimerTask实现:

private static class InterruptTimerTask extends TimerTask {
    private Thread thread;

    public InterruptTimerTask(Thread thread) {
        this.thread=thread;
    }

    @Override
    public void run() {
        thread.interrupt();
    }

}

答案 1 :(得分:1)

受到@NeplatnyUdaj答案的启发,我找到了这个解决方案:

try {
     ExecutorService executor = Executors.newSingleThreadExecutor();
     Future<String> future = executor.submit(new Task(rMIinstance));
     System.out.println("Result: "+ future.get(3, TimeUnit.SECONDS));

} catch (RemoteException | TimeoutException e) {
     getInstanceRegister().removeInstance(rMIinstance);
}

这项任务:

class Task implements Callable<String> {
        DatabaseAbstract rMIinstance;
        public Task(DatabaseAbstract rMIinstance)
        {
            this.rMIinstance = rMIinstance;
        }
        @Override
        public String call() throws Exception {
            rMIinstance.ping();
            return "OK";
        }
    }

答案 2 :(得分:0)

中断线程进行RMI调用的建议解决方案可能不起作用,具体取决于该线程是否处于可被中断的点。普通的正在进行的RMI调用是不可中断的。

尝试将系统属性java.rmi.server.disableHttp设置为true。可能正在发生长连接超时,因为RMI正在故障转移到其HTTP代理机制。在RMISocketFactory的类文档中描述了这种机制 - 虽然非常简短。 (在JDK 8中不推荐使用HTTP代理机制。)

答案 3 :(得分:0)

将系统属性sun.rmi.transport.proxy.connectTimeout设置为所需的连接超时(以毫秒为单位)。我也会设置sun.rmi.transport.tcp.responseTimeout

建议中断线程的答案依赖于java.net的特定于平台的行为,其中断时的行为未定义。