面试题答案
一键面试心跳消息格式
可以设计一个简单的JSON格式消息,例如:
{
"type": "heartbeat",
"timestamp": "当前时间戳"
}
type
字段表明这是心跳消息,timestamp
用于服务端判断消息顺序及是否有消息丢失。
发送频率
发送频率需要根据实际场景来设定。一般来说,如果网络环境较好且对实时性要求不是极高,可以设置为30秒到1分钟发送一次心跳消息。如果网络波动较大或者对实时连接状态要求非常严格,可能需要缩短到10 - 20秒发送一次。
处理心跳超时情况
- 客户端处理:
- 客户端发送心跳消息后,启动一个定时器。如果在设定时间(例如比发送频率略长,如发送频率为30秒,超时时间设为40秒)内没有收到服务端的心跳响应,客户端可以尝试重新连接WebSocket。
- 代码示例(JavaScript):
const socket = new WebSocket('ws://your - server - url');
let heartbeatTimer;
function sendHeartbeat() {
const heartbeat = {
type: 'heartbeat',
timestamp: new Date().getTime()
};
socket.send(JSON.stringify(heartbeat));
heartbeatTimer = setTimeout(() => {
console.log('Heartbeat timeout, attempting to reconnect...');
socket.close();
// 尝试重新连接
socket.open('ws://your - server - url');
}, 40000);
}
socket.addEventListener('open', () => {
sendHeartbeat();
});
socket.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
if (data.type === 'heartbeat - response') {
clearTimeout(heartbeatTimer);
sendHeartbeat();
}
});
- 服务端处理:
- 服务端收到心跳消息后,记录客户端的活跃时间。如果在一定时间(同样比心跳发送频率略长)内没有收到某个客户端的心跳消息,服务端可以主动关闭与该客户端的连接。
- 以Python的Tornado框架为例:
import tornado.ioloop
import tornado.web
import tornado.websocket
import time
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
self.last_heartbeat_time = time.time()
tornado.ioloop.IOLoop.current().call_later(60, self.check_heartbeat)
def on_message(self, message):
data = json.loads(message)
if data['type'] == 'heartbeat':
self.last_heartbeat_time = time.time()
response = {
'type': 'heartbeat - response',
'timestamp': time.time()
}
self.write_message(json.dumps(response))
def check_heartbeat(self):
if time.time() - self.last_heartbeat_time > 50:
self.close()
else:
tornado.ioloop.IOLoop.current().call_later(60, self.check_heartbeat)