面试题答案
一键面试设计思路
- 心跳包发送频率:设置合理的心跳包发送频率。频率过高会增加网络负担,过低则不能及时检测到网络异常。可根据网络环境和业务需求进行调整,初始可设为每5 - 10秒发送一次。
- 心跳包超时机制:为每个发送的心跳包设置超时时间。若在超时时间内未收到响应,判定为心跳包丢失,可能网络出现问题。超时时间应略大于心跳包发送频率,例如设置为15 - 20秒。
- 重试机制:当心跳包丢失时,进行重试。可设置固定次数的重试,如3次,每次重试间隔适当增加,避免短时间内大量重复请求加重网络负担。
- 状态管理:维护一个网络连接状态变量,根据心跳包的发送和响应情况更新状态。如“connected”表示正常连接,“disconnected”表示连接中断。
- 事件处理:定义事件,如“心跳成功”“心跳失败”“连接恢复”等,便于在应用的其他部分根据网络状态变化执行相应逻辑。
关键代码实现点
- 使用
net
模块(针对TCP连接):
const net = require('net');
const client = new net.Socket();
let heartbeatInterval;
let heartbeatTimeout;
let retryCount = 0;
let isConnected = false;
// 连接服务器
client.connect({ port: 8080, host: '127.0.0.1' }, () => {
console.log('Connected to server');
isConnected = true;
startHeartbeat();
});
function startHeartbeat() {
heartbeatInterval = setInterval(() => {
if (isConnected) {
sendHeartbeat();
}
}, 5000); // 每5秒发送一次心跳包
}
function sendHeartbeat() {
clearTimeout(heartbeatTimeout);
client.write('HEARTBEAT');
heartbeatTimeout = setTimeout(() => {
console.log('Heartbeat timeout, retry...');
if (retryCount < 3) {
sendHeartbeat();
retryCount++;
} else {
console.log('Max retry reached, consider connection lost');
isConnected = false;
clearInterval(heartbeatInterval);
// 触发连接丢失事件
}
}, 15000); // 15秒超时
}
client.on('data', (data) => {
if (data.toString() === 'HEARTBEAT_RESPONSE') {
console.log('Heartbeat response received');
retryCount = 0;
// 触发心跳成功事件
}
});
client.on('close', () => {
console.log('Connection closed');
isConnected = false;
clearInterval(heartbeatInterval);
clearTimeout(heartbeatTimeout);
});
client.on('error', (err) => {
console.error('Connection error:', err);
isConnected = false;
clearInterval(heartbeatInterval);
clearTimeout(heartbeatTimeout);
});
- 使用
http
模块(针对HTTP连接):
const http = require('http');
let heartbeatInterval;
let heartbeatTimeout;
let retryCount = 0;
let isConnected = false;
function sendHeartbeatRequest() {
clearTimeout(heartbeatTimeout);
const options = {
host: '127.0.0.1',
port: 3000,
path: '/heartbeat',
method: 'GET'
};
const req = http.request(options, (res) => {
if (res.statusCode === 200) {
console.log('Heartbeat response received');
retryCount = 0;
isConnected = true;
// 触发心跳成功事件
} else {
console.log('Unexpected status code:', res.statusCode);
handleHeartbeatFailure();
}
});
req.on('error', (err) => {
console.error('Heartbeat request error:', err);
handleHeartbeatFailure();
});
req.end();
heartbeatTimeout = setTimeout(() => {
console.log('Heartbeat timeout, retry...');
handleHeartbeatFailure();
}, 15000); // 15秒超时
}
function handleHeartbeatFailure() {
if (retryCount < 3) {
sendHeartbeatRequest();
retryCount++;
} else {
console.log('Max retry reached, consider connection lost');
isConnected = false;
clearInterval(heartbeatInterval);
// 触发连接丢失事件
}
}
function startHeartbeat() {
heartbeatInterval = setInterval(() => {
if (isConnected) {
sendHeartbeatRequest();
}
}, 5000); // 每5秒发送一次心跳包
}
// 启动HTTP服务器模拟接收心跳包
const server = http.createServer((req, res) => {
if (req.url === '/heartbeat' && req.method === 'GET') {
res.writeHead(200);
res.end('Heartbeat response');
} else {
res.writeHead(404);
res.end();
}
});
server.listen(3000, '127.0.0.1', () => {
console.log('Server listening on port 3000');
isConnected = true;
startHeartbeat();
});
上述代码分别展示了基于TCP和HTTP协议的心跳包机制实现示例,核心要点包括心跳包的发送、超时处理、重试逻辑以及状态管理等。实际应用中可根据具体业务场景进行调整和优化。