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

Node.js使用Socket.io刷新页面时socket连接数持续递增不释放问题排查

问题根因
  • 核心错误是你将Socket.io全局实例的connection事件监听逻辑放在了getPage路由处理函数中:每访问一次/temp页面(含刷新),就会给全局io实例新增一个重复的connection监听器,历史注册的监听器不会自动销毁。
  • 每次有新的Socket连接建立时,所有已注册的connection监听器都会同时触发,因此你会看到刷新N次后,connect日志会打印N条,对应disconnect事件也会被绑定N次,每条日志数量和页面访问次数完全匹配。
  • 每一个监听器都会持有对应socket实例的引用,导致断开的socket无法被垃圾回收,最终表现为连接数持续增长。
  • disconnect事件触发时socket本身已经在执行断开流程,你写的socket.disconnect(0)属于无效的冗余逻辑。
修复方案

将connection事件监听逻辑从路由处理函数中移出,在server.js中全局仅注册一次即可:

  1. 修改server.js代码:
const app = express();
const server = require("http").createServer(app);
const io = require("socket.io")(server);

// 全局仅注册一次连接监听
io.on('connection', (socket) => {
  console.log('connect');
  socket.on('disconnect', () => {
    console.log('disconnect');
  });
});

app.use((req, res, next) =>{
    req.io = io;
    next();
});

const temp = require("./routes/temp");
app.use("/temp", temp);
  1. 修改controller层getPage代码,移除重复的监听逻辑:
getPage(req, res, io){
    console.log('re');
    // 剩余业务逻辑保留即可
}
补充注意事项

如果业务场景需要在页面请求时对应当前用户的socket实例做操作,不要重复注册connection监听,可通过如下方式实现:

  • 建立全局Map存储用户标识与socket实例的映射关系
  • 在全局connection监听中,将登录用户的id和socket绑定存入Map
  • 路由处理时从请求中拿到用户id,再从Map中取出对应socket实例执行操作即可

内容的提问来源于stack exchange,提问作者재창킴

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 19:39:04