Java RMI 客户端丢失连接

Java RMI client loss connection

我正在使用 Java RMI 构建分布式应用程序。

每当代理向服务器注册时,服务器都会进行一些计算(例如,将代理添加到数组中)。并且代理不断向服务器发送活跃度消息。

我想要的是,每当代理停止发送此消息或连接丢失时,服务器都会注意到并重新计算(例如,从列表中删除客户端)

最好的方法是什么?

我看到一些解决方案 ping 客户端或使用多线程。任何建议表示赞赏

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

1) 双向生命线

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

好处:连接中断时立即通知。

缺点:每次连接都要在服务端和客户端维护一个新的线程,断开逻辑比较复杂。

2) 心跳

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

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

缺点: 较慢的断开连接响应时间(直至 ping 调用之间的延迟),在失败的 ping() 调用期间易受长 TCP 超时的影响。

那么最好的路线是什么?

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

第三个选项可能是查看 RMI 对 Server/SocketFactory 实现的使用,并尝试 link 远程对象到 RMI 创建的特定套接字。我以前做过这个,但这不是一个快速的解决方案,尽管它可以以最少的开销为您提供两全其美的方法。

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

注意 RMI 中并没有 'loses connection' 这样的东西。它的底层连接一直来来去去,受制于连接池,在 API 级别根本没有连接。