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

Socket.io Node.js集群环境下同一事件重复触发问题求助

Socket.io集群下事件重复触发的问题解决

问题根源

  1. 版本不兼容:你使用的@socket.io/sticky是为Socket.io v3+开发的工具,和当前使用的v2.0.5版本完全不兼容,这会导致连接分配逻辑混乱,直接引发事件重复发送。
  2. 冗余服务实例:Worker进程中额外创建了httpServer实例,虽然未监听端口,但会干扰sticky session的正常工作流程,加剧连接处理异常。
  3. 广播逻辑叠加:结合Redis适配器使用io.to('data').emit时,版本不兼容会导致事件被当前Worker和其他Worker重复广播,最终客户端收到多次相同事件。

修复方案

第一步:替换兼容的sticky session工具

卸载不兼容的@socket.io/sticky,安装适配Socket.io v2的sticky-session:

npm uninstall @socket.io/sticky
npm install sticky-session

第二步:修正服务端代码

const cluster = require("cluster");
const http = require("http");
const { Server } = require("socket.io");
const redisAdapter = require("socket.io-redis");
const sticky = require("sticky-session");

const server = http.createServer();

// 启动sticky session集群
if (!sticky.listen(server, 3000)) {
  // Master进程逻辑
  console.log(`Master ${process.pid} 已启动`);
  cluster.on("exit", (worker) => {
    console.log(`Worker ${worker.process.pid} 已退出,重启中...`);
    cluster.fork();
  });
} else {
  // Worker进程逻辑
  console.log(`Worker ${process.pid} 已启动`);
  const io = new Server();
  io.attach(server);
  // 配置Redis适配器,确保本地Redis服务正常运行
  io.adapter(redisAdapter({ host: "localhost", port: 6379 }));

  io.on("connection", (socket) => {
    console.log("新客户端连接");
    socket.join("data");
    // 如果仅需给当前连接的客户端发送事件,用socket.emit更高效,避免不必要的广播
    // socket.emit("event", "data");
    // 若需给整个房间发送事件,确保socket.io-redis版本为5.x(与Socket.io v2.0.5兼容)
    io.to('data').emit("event", "data");
  });
}

额外提示

  • 如果业务允许,建议直接升级Socket.io到v3+版本,配合官方的@socket.io/sticky使用,兼容性和稳定性会更有保障。
  • 检查Redis服务是否正常启动,避免因Redis连接失败导致的适配器逻辑异常。

内容的提问来源于stack exchange,提问作者İrem Simsar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 04:55:05