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

如何在Node.js服务重启前关闭WebSocket客户端的所有现有连接

错误原因

你调用close()报错的核心问题是:存入sockets数组的是WebSocketClient实例,该实例仅用于发起连接,本身没有close方法。真正控制连接的close方法挂载在connect事件回调返回的connection对象上。

代码修复

以下是调整后的可运行代码:

const WebSocketClient = require('websocket').client;
const axios = require('axios');
let sockets = [];
// 移除无用的client入参
function openSocket(id){
  const client = new WebSocketClient();
  client.on('connectFailed', function(error) {
      console.log('Connect Error 1: ' + error);
  });

  client.on('connect', function(connection) {
      console.log('WebSocket Client Connected for id:' + id);
      // 将可用的connection存入数组
      sockets.push(connection);
      
      connection.on('error', function(error) {
          console.log("Connection Error 2: " + error.toString());
      });
      connection.on('close', function() {
          console.log('echo-protocol Connection Closed for id:' + id);
          // 连接关闭后从数组中移除,避免存储无效引用
          sockets = sockets.filter(item => item !== connection);
      });
      connection.on('message', function(message) {
          let {utf8Data:socketResData} = message;
          console.log(socketResData);
      });

      function subscribe(){
          if (connection.connected) {
              connection.send(JSON.stringify(
                  {
                      action: "SubscribeToAuction",
                      data: id
                  }
              ));
          }
      }
      subscribe();
      
      function pingServer() {
          if (connection.connected) {
              connection.send(JSON.stringify(
                  {
                      action: "Ping",
                  }
              ));
              // 保存定时器id,连接关闭时清除避免内存泄漏
              connection.pingTimer = setTimeout(pingServer, 540000);
          }
      }
      pingServer();

  });
  // 这里替换成你实际的socketUrl
  client.connect(socketUrl,null,{"x-forwarded-client-id":id},null);
}

// 封装关闭所有连接的方法
function closeAllSockets() {
  sockets.forEach(connection => {
    if (connection.connected) {
      // 清除心跳定时器
      clearTimeout(connection.pingTimer);
      connection.close();
    }
  });
  // 清空数组
  sockets = [];
}

function run(){
  // 每次新建连接前先关闭已有连接,避免重复创建
  closeAllSockets();
  // 这里替换成你实际的请求参数
  axios(url, {
      method: 'GET',
      headers: {
          authority,
          'x-forwarded-client-id': id,
      },
  }).then(res => {
      const auction = res.data.models.HomePageModel.upcomingModel.upcomingAuctions;
      auction.forEach(el => {
        openSocket(el.auctionUuid)
      });
  }).catch(err => console.log(err))
}
run();

// 监听进程退出信号,服务重启/停止时主动关闭所有连接
process.on('SIGINT', closeAllSockets);
process.on('SIGTERM', closeAllSockets);

// 测试用的关闭逻辑,可保留验证
setTimeout(() => {
  closeAllSockets();
  console.log('所有连接已关闭');
},10000)
场景最佳实践
  • 连接去重:可以用Map替代数组存储连接,key为auctionUuid,建立连接前先判断对应key是否已存在活跃连接,避免重复订阅相同资源
  • 重连逻辑:单个连接断开后可按指数退避策略重连,避免频繁请求第三方服务
  • 状态监控:定期遍历连接列表,清理长时间无响应的死连接
  • 优雅退出:所有进程退出场景都要主动关闭连接,避免服务端残留半开连接

内容的提问来源于stack exchange,提问作者sameed ul hassan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 11:45:04