You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebSocket连接短暂断开,如何维持长连接及架构相关咨询

WebSocket短暂连接后断开问题排查与解答

问题描述

尝试连接API中的WebSocket,但仅能短暂建立连接后就断开。以下是相关代码与日志:

前端HTML脚本代码

const ws = new WebSocket('ws://localhost:1337')
ws.addEventListener('open', (event) => {
    ws.send(JSON.stringify({title: 'like that', message: 'gimme update'}));
})

ws.addEventListener('close', (close) => {
    console.log(JSON.stringify(close))
})
ws.addEventListener('message', (event) => {
    const dataFromServer = JSON.parse(event.data);
    console.log('Message from server', JSON.parse(event.data))
    const h1 = document.getElementById('changeHere');
    h1.innerText = `Changing: ${dataFromServer.statusId}`
})

后端代码

...
const websocket = new WebSocket.Server({ server: httpServer });

const TAG_WEBSOCKET = '[WEBSOCKET]';

websocket.on('connection', (connection) => {
  connection.on('error', (err) => console.error);
  logger.info('client connected');
  connection.send('message');
  emitter.on('updateStatus', (data) => {
    logger.info(TAG_WEBSOCKET + 'Update status for ' + data.id);
    connection.send(JSON.stringify(data));
  });
  connection.on('close', () => {
    logger.info('connection closed');
    emitter.removeAllListeners();
  });
});

httpServer.listen(PORT, () => {
    logger.info(`${TAG} Server running on port: ${PORT}`);
  });

后端日志

2023-01-04 21:28:44 [info] client connected
info: Client disconnect: undefined
error: Can not find client undefined on disconnect
2023-01-04 21:28:44 [info] connection closed

咨询问题:

  1. 如何实现客户端在线时保持WebSocket长连接?
  2. 该问题是否与API被大量非WebSocket客户端使用有关?
  3. 是否需要为WebSocket单独搭建专用API?

解决方案与解答

1. 实现WebSocket长连接的关键修复与优化

当前连接断开的核心原因是代码逻辑错误,需针对性修复:

  • 修复JSON解析错误:后端在连接建立后发送的'message'是纯字符串,前端尝试用JSON.parse解析会抛出语法错误,可能触发连接异常。需将后端初始消息改为合法JSON:
    // 后端修改初始发送内容
    connection.send(JSON.stringify({type: 'init', message: 'connected'}));
    
    前端也可增加解析容错:
    ws.addEventListener('message', (event) => {
        let dataFromServer;
        try {
            dataFromServer = JSON.parse(event.data);
            console.log('Message from server', dataFromServer);
            const h1 = document.getElementById('changeHere');
            if (dataFromServer.statusId) {
                h1.innerText = `Changing: ${dataFromServer.statusId}`;
            }
        } catch (e) {
            console.warn('Received non-JSON message:', event.data);
        }
    })
    
  • 修正监听器移除逻辑:后端在close事件中调用emitter.removeAllListeners()会移除所有updateStatus事件的监听器,导致其他在线客户端无法接收消息,还可能间接影响当前连接生命周期。应改为移除当前连接对应的特定监听器:
    websocket.on('connection', (connection) => {
      // 单独定义监听函数,方便后续移除
      const updateStatusHandler = (data) => {
        logger.info(TAG_WEBSOCKET + 'Update status for ' + data.id);
        connection.send(JSON.stringify(data));
      };
      emitter.on('updateStatus', updateStatusHandler);
    
      connection.on('close', () => {
        logger.info('connection closed');
        // 仅移除当前连接的监听器
        emitter.off('updateStatus', updateStatusHandler);
      });
    });
    
  • 增加心跳机制:避免网络超时或中间设备主动断开空闲连接,实现心跳交互:
    • 前端:每隔30秒发送心跳包
      let heartbeatTimer;
      ws.addEventListener('open', () => {
          heartbeatTimer = setInterval(() => {
              if (ws.readyState === WebSocket.OPEN) {
                  ws.send(JSON.stringify({type: 'ping'}));
              }
          }, 30000);
      });
      
      ws.addEventListener('close', () => {
          clearInterval(heartbeatTimer);
      });
      
    • 后端:收到心跳包后返回响应
      connection.on('message', (message) => {
        const data = JSON.parse(message);
        if (data.type === 'ping') {
            connection.send(JSON.stringify({type: 'pong'}));
        }
        // 处理其他业务消息
      });
      
  • 完善错误处理:后端错误监听需传入错误参数,便于排查问题:
    connection.on('error', (err) => console.error('WebSocket connection error:', err));
    

2. 与大量非WebSocket客户端的关联性

普通HTTP请求(非WebSocket客户端)不会直接导致WebSocket连接断开,只要服务器资源(CPU、内存、文件描述符)充足,两者可以共存。从当前日志看,连接后立即断开更可能是代码逻辑错误导致,而非非WebSocket客户端的影响。若服务器资源紧张(如CPU占用过高),可能间接影响连接稳定性,可通过监控服务器资源使用情况排除该因素。

3. 是否需要单独搭建WebSocket专用API

不是必须的,需根据业务规模与需求判断:

  • 无需拆分场景:当前业务量不大,普通HTTP请求与WebSocket的资源需求差异小,共用一个服务器可简化部署与维护。
  • 建议拆分场景:
    • WebSocket并发量极高,需要独立扩容或资源隔离;
    • 普通HTTP API的中间件(如认证、CORS)与WebSocket逻辑冲突,拆分后可简化配置;
    • 业务逻辑复杂度高,拆分后便于单独维护与迭代。

当前问题属于代码逻辑错误,优先修复代码即可,无需立即拆分API。


内容的提问来源于stack exchange,提问作者Lucas Lima

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 20:50:29