简体   繁体   English

Java RMI客户端丢失连接

[英]Java RMI client loss connection

I am building a distributed application with Java RMI. 我正在使用Java RMI构建分布式应用程序。

Whenever an agent register to the server, the server does some calculation (eg, 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 (eg, 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. 我看到一些对客户端执行ping操作或使用多线程的解决方案。 Any advice is appreciated 任何建议表示赞赏

There's a couple of ways you could do this, and each have associated benefits and drawbacks. 您可以通过两种方法来完成此任务,每种方法都有各自的优点和缺点。

1) Bidirectional Lifeline 1)双向生命线

In this solution, your server and client would both have lifeline() methods that effectively block forever. 在此解决方案中,您的服务器和客户端都将具有有效地永远阻止的lifeline()方法。 If the connection goes down, a RemoteException will get thrown immediately in this method call. 如果连接断开,此方法调用中将立即引发RemoteException If the client initiated the call, it can either attempt to reconnect to the server or exit. 如果客户端发起了呼叫,则它可以尝试重新连接到服务器或退出。 The server will have to maintain some logic so that server.lifeline() called by the client can return if the client disconnects (detected by exception when server calling client.lifeline() results in exception), otherwise you'll have dangling threads on the server that block forever, consuming resources until your server runs out of memory. 服务器必须维护一些逻辑,以便如果客户端断开连接,则由客户端调用的server.lifeline()可以返回(当服务器调用client.lifeline()导致异常时被异常检测到),否则您的线程将悬空永远阻塞的服务器,直到服务器内存用完为止,都会消耗资源。

Benefits: Immediate notification when connections die. 好处:连接中断时立即通知。

Drawbacks: A new thread on server and client must be maintained for every connection, more complicated disconnect logic. 缺点:必须为每个连接维护服务器和客户端上的新线程,更复杂的断开逻辑。

2) Heartbeat 2)心跳

In this case, you still have one thread on each client calling server.ping() every few seconds, but you only need one thread on the server calling client.ping() , every few seconds per connected client on average. 在这种情况下,每个客户端上仍然每隔几秒就有一个线程调用server.ping() ,但是每个连接的客户端平均每隔几秒钟只需要有一个线程调用client.ping() If any ping() call results in an exception, you know that you are disconnected. 如果有任何ping()调用导致异常,则说明您已断开连接。

Benefits: Simpler connection logic, fewer resources consumed on the server due to fewer threads managing connection state. 好处:连接逻辑更简单,由于管理连接状态的线程更少,服务器上消耗的资源更少。

Drawbacks: Slower disconnect response times (up to delay between ping calls), susceptible to long TCP timeouts during failed ping() calls. 缺点:断开连接响应时间更短(最多可达ping调用之间的延迟),在ping()调用失败期间易受长时间TCP超时的影响。

So what's the best route? 那么最好的路线是什么?

I think this depends totally on what your app is trying to do. 我认为这完全取决于您的应用正在尝试执行的操作。 If you need the absolute most up-to-date information on the state of your network as soon as possible, then the first approach will give you that. 如果您需要尽快获得有关网络状态的绝对最新信息,那么第一种方法将为您提供信息。 If you can tolerate a delay in detecting disconnects, the second approach is better. 如果您可以忍受检测到断开连接的延迟,则第二种方法更好。

A third option could be to look into RMI's usage of Server/SocketFactory implementations and try to link remote objects to specific sockets created by RMI. 第三种选择是研究RMI对Server/SocketFactory实现的使用,并尝试将远程对象链接到RMI创建的特定套接字。 I've done this before but it's not a quick solution, although it can give you the best of both worlds with the least overhead. 我之前已经做过,但这不是一个快速的解决方案,尽管它可以以最少的开销为您提供两全其美的解决方案。

Have your server issue each client with a unique remote object, say a remote session for example, that implements Unreferenced , and have the unreferenced() method implementation implement the logic you require. 让服务器为每个客户端分配一个唯一的远程对象,例如一个实现Unreferenced的远程会话,并让unreferenced()方法实现实现您所需的逻辑。

NB There isn't really such a thing as 'loses connection' in RMI. 注意:在RMI中,并没有真正的“失去连接”之类的东西。 Its underlying connections come and go all the time, subject to connect pooling, and at the API level there is no connection at all. 它的基础连接一直在变化,取决于连接池,在API级别上根本没有连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM