【发布时间】:2016-08-31 18:47:16
【问题描述】:
我正在使用 Java RMI 构建分布式应用程序。
每当代理注册到服务器时,服务器都会进行一些计算(例如,将代理添加到数组中)。并且代理不断向服务器发送活跃消息。
我想要的是,每当代理停止发送此消息或连接丢失时,服务器都会注意到并重新计算(例如,从列表中删除客户端)
最好的方法是什么?
我看到一些解决方案 ping 客户端或使用多线程。任何建议表示赞赏
【问题讨论】:
标签: java client-server rmi
我正在使用 Java RMI 构建分布式应用程序。
每当代理注册到服务器时,服务器都会进行一些计算(例如,将代理添加到数组中)。并且代理不断向服务器发送活跃消息。
我想要的是,每当代理停止发送此消息或连接丢失时,服务器都会注意到并重新计算(例如,从列表中删除客户端)
最好的方法是什么?
我看到一些解决方案 ping 客户端或使用多线程。任何建议表示赞赏
【问题讨论】:
标签: java client-server rmi
有几种方法可以做到这一点,每种方法都有相关的优点和缺点。
1) 双向生命线
在此解决方案中,您的服务器和客户端都将具有lifeline() 方法,可以有效地永久阻塞。如果连接断开,RemoteException 将在此方法调用中立即抛出。如果客户端发起了调用,它可以尝试重新连接到服务器或退出。服务器必须维护一些逻辑,以便客户端调用的server.lifeline() 可以在客户端断开连接时返回(当服务器调用client.lifeline() 导致异常时被异常检测到),否则您将在服务器上有悬空线程阻塞永远消耗资源,直到你的服务器内存不足。
好处:连接中断时立即通知。
缺点:每个连接都必须在服务器和客户端上维护一个新线程,更复杂的断开逻辑。
2) 心跳
在这种情况下,每个客户端上仍有一个线程每隔几秒调用一次server.ping(),但服务器上只需要一个线程调用client.ping(),平均每个连接的客户端每隔几秒调用一次。如果任何ping() 调用导致异常,您就知道您已断开连接。
好处:更简单的连接逻辑,由于管理连接状态的线程更少,服务器上消耗的资源更少。
缺点:较慢的断开响应时间(直到 ping 调用之间的延迟),在 ping() 调用失败期间容易受到长时间 TCP 超时的影响。
那么最好的路线是什么?
我认为这完全取决于您的应用想要做什么。如果您需要尽快获得有关网络状态的最新绝对信息,那么第一种方法将为您提供。如果您可以容忍检测断开连接的延迟,则第二种方法更好。
第三种选择可能是查看 RMI 对 Server/SocketFactory 实现的使用,并尝试将远程对象链接到 RMI 创建的特定套接字。我以前做过,但这不是一个快速的解决方案,尽管它可以以最少的开销为您提供两全其美的效果。
【讨论】:
让您的服务器向每个客户端发出一个唯一的远程对象,例如实现Unreferenced 的远程会话,并让unreferenced() 方法实现实现您需要的逻辑。
NB 在 RMI 中并没有真正意义上的“失去连接”。它的底层连接一直来来去去,受连接池的影响,在 API 级别根本没有连接。
【讨论】:
unrefrenced() 通知服务器。我该怎么做?