我需要在我的 Java 项目(3-5 个客户端和 1 个服务器)上实现一个心跳系统,但我有一些问题。
1) 客户需要 2 个 socket 吗? 1 个用于心跳,1 个用于接收我的软件的正常消息
2) 我看到在客户端滞后的特定情况下,客户端收不到消息,如何避免这种情况?
3) 如果客户端断开连接,如何恢复与它的连接?无需使用它重新创建新套接字。
最佳答案
因此,您有一个“中央服务器”,需要为客户端提供心跳机制。好吧,部分解决方案很简单,因为您只有一台服务器,这简化了很多,因为您不需要处理数据复制、数据同步机制、服务器故障等。您只是期望您的服务器永远不会出现故障,如果出现故障,则会出现致命错误。
我的建议是实现一个基于通知的系统(池化是糟糕且丑陋的):不是让服务器池化客户端,而是让客户端每 X 秒向服务器报告一次状态。这减少了系统的一般过载,它基于“Tell, don't ask”的设计原则。这还允许您为每个客户设置不同的报告时间。
还有一个问题,你要传输什么数据?只要客户还活着?客户端的运行时数据,例如,如果客户端正在下载文件,则完成工作的百分比?环境状态,如 CPU 过载、内存使用、网络状态?定义它,这是第一步。
谈到 java 实现,您应该在每个客户端上运行一个线程(实现 Runnable 接口(interface))。它看起来应该类似于以下代码(为简洁起见进行了简化):
public class HeartbeatAgent implements Runnable {
private int DEFAULT_SAMPLING_PERIOD = 5; //seconds
private String DEFAULT_NAME = "HeartbeatAgent";
private HashMap<Integer, Object> values; // <id, value>
public HeartbeatAgent () {
values = new HashMap<Integer,Object>();
}
private void collect() {
/** Here you should collect the data you want to send
and store it in the hash
**/
}
public void sendData(){
/** Here you should send the data to the server. Use REST/SOAP/multicast messages, whatever you want/need/are forced to **/
}
public void run() {
System.out.println("Running " + DEFAULT_NAME );
try {
while( /** condition you want to stop **/ {
System.out.println("Thread: " + DEFAULT_NAME + ", " + "I'm alive");
this.collect();
this.send();
// Let the thread sleep for a while.
Thread.sleep(DEFAULT_SAMPLING_PERIOD * 1000);
}
} catch (InterruptedException e) {
System.out.println("Thread " + DEFAULT_NAME + " interrupted.");
}
System.out.println("Thread " + DEFAULT_NAME + " exiting.");
}
}
您应该编写一个服务器来处理所发出的请求,并且足够“智能”以在没有来自客户端 Y 的“消息”的情况下在 X 秒后调用超时。
这仍然不理想,因为您收集数据并以相同的采样周期发送数据,但通常您希望以非常小的间隔收集数据(例如,每 5 秒收集一次 CPU 使用率),但仅每 30 秒报告一次秒。
如果您想查看执行此操作的优秀库的优秀代码(这是我们在我公司的项目中一直使用的代码),请查看 JCatascopia框架代码(只看 Agent 和 Server 文件夹,忽略其他文件夹)。
这个话题要说的很多,这是基本的。欢迎提问!
关于Java心跳设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33869092/