MST

星途 面试题库

面试题:Node.js 中如何实现简单的心跳检测机制

请简述在Node.js网络通信中,实现心跳检测机制的基本思路,并给出一个简单的代码示例(可以基于TCP或HTTP协议)。
24.0万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

基本思路

  1. 客户端
    • 定期向服务器发送心跳包,告知服务器自己处于活跃状态。
    • 启动定时器,按照固定时间间隔发送心跳消息。
    • 处理服务器返回的心跳响应,若长时间未收到响应,可认为连接异常。
  2. 服务器
    • 接收客户端发送的心跳包,并记录客户端的活跃状态。
    • 为每个客户端设置一个心跳超时时间,若在该时间内未收到客户端的心跳包,则判定客户端离线。

TCP协议代码示例

服务端代码(server.js)

const net = require('net');
const clients = new Map();
const HEARTBEAT_TIMEOUT = 5000; // 心跳超时时间5秒

const server = net.createServer((socket) => {
    socket.id = Date.now();
    clients.set(socket.id, socket);
    socket.on('data', (data) => {
        const message = data.toString().trim();
        if (message === 'heartbeat') {
            socket.heartbeatReceived = Date.now();
            socket.write('heartbeat response\n');
        }
    });
    socket.on('end', () => {
        clients.delete(socket.id);
    });
});

server.listen(8080, () => {
    console.log('Server listening on port 8080');
});

setInterval(() => {
    const now = Date.now();
    clients.forEach((socket, id) => {
        if (!socket.heartbeatReceived || now - socket.heartbeatReceived > HEARTBEAT_TIMEOUT) {
            console.log(`Client ${id} timeout, closing connection`);
            socket.end();
            clients.delete(id);
        }
    });
}, HEARTBEAT_TIMEOUT);

客户端代码(client.js)

const net = require('net');
const HEARTBEAT_INTERVAL = 3000; // 心跳发送间隔3秒

const client = net.connect({ port: 8080 }, () => {
    console.log('Connected to server');
    setInterval(() => {
        client.write('heartbeat\n');
    }, HEARTBEAT_INTERVAL);
});

client.on('data', (data) => {
    const message = data.toString().trim();
    if (message === 'heartbeat response') {
        console.log('Received heartbeat response from server');
    }
});

client.on('end', () => {
    console.log('Connection closed by server');
});

HTTP协议代码示例

服务端代码(server.js)

const http = require('http');
const express = require('express');
const app = express();
const clients = new Map();
const HEARTBEAT_TIMEOUT = 5000; // 心跳超时时间5秒

app.get('/heartbeat', (req, res) => {
    const clientIp = req.ip;
    clients.set(clientIp, Date.now());
    res.send('heartbeat response');
});

const server = http.createServer(app);
server.listen(3000, () => {
    console.log('Server listening on port 3000');
});

setInterval(() => {
    const now = Date.now();
    clients.forEach((lastHeartbeat, clientIp) => {
        if (now - lastHeartbeat > HEARTBEAT_TIMEOUT) {
            console.log(`Client ${clientIp} timeout`);
            clients.delete(clientIp);
        }
    });
}, HEARTBEAT_TIMEOUT);

客户端代码(client.js)

const axios = require('axios');
const HEARTBEAT_INTERVAL = 3000; // 心跳发送间隔3秒

setInterval(() => {
    axios.get('http://localhost:3000/heartbeat')
      .then(response => {
            console.log('Received heartbeat response from server');
        })
      .catch(error => {
            console.error('Error sending heartbeat:', error);
        });
}, HEARTBEAT_INTERVAL);