Java RMI client loss connection

时间:2016-08-31 18:47:16

标签: java client-server rmi

I am building a distributed application with Java RMI.

Whenever an agent register to the server, the server does some calculation (e.g, adds the agent to an array). And the agents keep sending liveliness messages to the server.

What I want is that whenever an agents stops sending this message or the connection gets lost, the server notice that and recalculate (e.g, deletes the client from the list)

What is the best way to do this?

I saw some solutions ping the clients or use multi-threads. Any advice is appreciated

2 个答案:

答案 0 :(得分:0)

有几种方法可以做到这一点,每种方法都有相关的好处和缺点。

1)双向生命线

在此解决方案中,您的服务器和客户端都有lifeline()个方法可以永久阻止。如果连接断开,则会在此方法调用中立即抛出RemoteException。如果客户端发起了呼叫,它可以尝试重新连接到服务器或退出。服务器必须维护一些逻辑,以便客户端调用的server.lifeline()可以在客户端断开连接时返回(在服务器调用client.lifeline()导致异常时由异常检测到),否则您将有悬空线程永远阻塞的服务器,消耗资源直到服务器内存不足。

好处:连接死亡时立即通知。

缺点:必须为每个连接维护服务器和客户端上的新线程,更复杂的断开逻辑。

2)心跳

在这种情况下,每隔几秒就会在每个客户端上调用server.ping()一个线程,但是您只需要在服务器上调用client.ping()一个线程,平均每个连接客户端每隔几秒钟。如果任何ping()调用导致异常,则表示您已断开连接。

好处:更简单的连接逻辑,由于管理连接状态的线程更少,服务器上消耗的资源更少。

缺点:较慢的断开响应时间(ping呼叫之间的延迟),在ping()次呼叫失败期间容易受到长TCP超时的影响。

那么什么是最好的路线?

我认为这完全取决于您的应用尝试做什么。如果您需要尽快获得有关网络状态的绝对最新信息,那么第一种方法将为您提供。如果您能够容忍延迟检测断开连接,则第二种方法更好。

第三种选择可能是研究RMI对Server/SocketFactory实现的使用,并尝试将远程对象链接到RMI创建的特定套接字。我以前做过这个,但它不是一个快速的解决方案,虽然它可以以最少的开销为你提供两个世界中最好的。

答案 1 :(得分:0)

让您的服务器向每个客户端发出一个唯一的远程对象,例如一个实现Unreferenced的远程会话,并让unreferenced()方法实现实现您需要的逻辑。

注意:在RMI中确实没有“丢失连接”这样的事情。它的底层连接始终存在,取决于连接池,并且在API级别根本没有连接。