我怎样才能保证“活下去”? 心跳发送了?
我们有一个用 Java 编写的 RMI 客户端应用程序,它需要定期向服务器应用程序发送“保持活动”消息。 我们将其实现为一个单独的心跳线程,它将保持活动消息发送到服务器,然后使用 Thread.sleep() 休眠 15 秒。
线程设置为高优先级:
Thread heartbeatThread = new Thread(new HeartbeatRunnable(server));
heartbeatThread.setPriority(Thread.MAX_PRIORITY);
heartbeatThread.start();
但是,当运行客户端的机器使用大量 CPU 时,我们发现心跳丢失,这导致服务器假设我们的客户端应用程序已经死亡。
我们在我的主线程中添加了 Thread.yield() 调用,尽管这并没有使问题消失。
有什么方法可以保证在我的应用程序仍在运行时按时发送心跳?
We have an RMI client application written in Java which needs to send periodic "stay alive" messages to a server application. We have implemented this as a separate heartbeat thread, which sends the stay alive message to the server, then sleeps for 15 seconds using Thread.sleep().
The thread is set to be high priority:
Thread heartbeatThread = new Thread(new HeartbeatRunnable(server));
heartbeatThread.setPriority(Thread.MAX_PRIORITY);
heartbeatThread.start();
However, when the box on which the client is running is using lots of CPU, we find that heartbeats are missed, which causes the server to assume our client application has died.
We have added Thread.yield() calls in my main thread, although this has not made the problem go away.
Is there any way of guaranteeing that heartbeats are sent on time while my application is still running?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
你不能真正保证它。 您可以在不同的线程中发送心跳,以防止发送心跳所花费的时间被添加到延迟中。 还建议将两次心跳之间的延迟设置为服务器用于确定客户端已死亡的时间的一半,即,如果服务器在 15 秒后超时,则(尝试)每 7.5 秒发送一次心跳。
You can not really guarantee it. You could send the heartbeat in a different thread to prevent the time it takes to send the heartbeat being added to your delay. It may also be advisable to set the delay between two heartbeats to half the time the server uses to decide a client is dead, i.e. if your server times out your client after 15 seconds, (try to) send a heartbeat every 7.5 seconds.
这取决于哪个进程正在使用CPU。
如果这不是您的进程,并且客户端进程确实没有响应,那么它实际上并不存在,因此不发送心跳是适当的。 当盒子负载过重而无法处理消息时,显示一条心跳消息会产生误导。
如果心跳消息的目的是说“此进程正在运行,但可能需要半个小时才能回复您”,那么让正在执行该处理的任何内容将该消息发送到服务器。 或者将超时设置为适合客户端响应能力的超时。
It depends what process is using the CPU.
If it's not your process, and so the client process really is unresponsive, then it is to all intents and purposes not alive, so not sending a heartbeart is appropriate. Having a heartbeat message which says 'I'm up and can process messages' when the box is too loaded to do that would be misleading.
If the intent of the heartbeat message is to say 'this process is running, but it might be half an hour until I get back to you', then have whatever is doing that processing send that message to the server. Or set the timeout to one that fits with the responsiveness of the client.
您可以通过在代码中随意分散自编写的“yield”函数来在非线程环境中实现用户模式线程。
同样,您可以在代码中随意分散心跳检查函数调用。 放弃线程,只需定期调用心跳函数来检查是否需要发送心跳。
这是一个粗略的解决方案,但考虑到您已经尝试了正确的解决方案并且它不起作用,也许您必须回退到它。
事实上,您可以做的是在每个函数调用的开头放置一个宏,它会快速检查时间并在必要时调用心跳函数。
(啊,Java 中有宏吗?我想没有 - 但你明白了)。
You can implement user-mode threading in a non-threaded environment by liberally scattering a self-written "yield" function in your code.
Similarly, you could liberally scatter heartbeat check function calls in your code. Forgo the thread, simply regularly call a heartbeat function which checks to see if a heartbeat yet needs to be sent.
It's a crude solution, but given you've tried the proper solution and it doesn't work, perhaps it's something you have to fall back to.
In fact what you could do is place a macro at the beginning of every function call, which does a quick check on the time and calls the heartbeat function when necessary.
(Ah, do you have macros in Java? I think not - but you get the idea).
您应该配置服务器在确定客户端不可用之前等待的“错过的心跳”数量。
因此,例如,如果您的心跳间隔为 15 秒,而错过的心跳次数为 4,则服务器将等待最多 60 秒(1 分钟),然后才确定客户端无法访问。
You should configure the number of "missed heartbeats" that the server waits before deciding that the client is unavailable.
So, for example, if your heartbeat interval is 15 seconds and the number of missed heartbeats is 4, then the server will wait upto a maximum of 60 seconds (1 min) before deciding that the client is unreachable.
也许最好的解决方案是使用 Timer 的 scheduleAtFixedRate。 这样,如果一个执行延迟(这在 Java 中无法避免),后续调用将不会受到影响。
Perhaps the best solution would be to use Timer's scheduleAtFixedRate. With this, if one execution delays (which can't be avoided in Java), the subsequent calls won't be affected.
如果您希望服务器宣布它还活着,那么最好提供一个打开的套接字。 在您的客户端上,只需从该套接字读取即可。 它会阻塞(因为你的服务器没有写任何东西),如果服务器消失/关闭,你的客户端将得到一个 IOException ,表明服务器套接字/端口已经消失。
这不依赖于服务器提供及时的心跳。 它使用很少的资源(服务器端的 TCP 端口,几乎没有带宽),并且可以及时显示服务器(或服务器计算机)何时变得不可用。
If you want the server to announce that it's alive, you may be better off presenting an open socket. On your client simply read from that socket. It'll block (since your server isn't writing anything), and if the server disappears/shuts down your client will get an IOException indicating that the server socket/port has disappeared.
This won't be dependent on the server providing timely heartbeats. It uses few resources (a TCP port on the server end and next to no bandwidth) and it is timely in revealing when the server (or server machine) becomes unavailable.