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

如何在已有Next.js项目中结合PM2正确配置Socket.io(多Worker场景)

问题:Next.js视频聊天PM2部署后跨进程Socket交互失效

我为现有Next.js应用开发的视频聊天功能本地运行正常,但部署到PM2后失效。核心问题是当用户执行JOIN_ROOM操作时,io.sockets.adapter.rooms.get(roomID)可能返回空数组——因为用户可能连接在其他PM2 Worker进程上。

现有核心代码

const nextApp = next({ dev: config.dev });
nextApp.prepare()
.then(() => {
    const app: Express = express();
    const server: http.Server = http.createServer(app);
    const io: socketio.Server = new socketio.Server();
    io.attach(server);
    io.on('connection', (socket: socketio.Socket) => {
        console.log('Socket connected!!!');
        socket.on(SOCKET_ACTIONS.JOIN_ROOM, data => {
            let { room: roomID } = data;
            const { rooms: joinedRooms } = socket;
            if (Array.from(joinedRooms).includes(roomID)) {
                return console.warn('Already connected');
            }
            const clients = Array.from(io.sockets.adapter.rooms.get(roomID) || []);
            console.log('socket clients: ', clients); // 可能返回空数组,因为用户在其他PM2进程
            clients.forEach(clientID => {
                // 已有用户添加新用户到自己的对等列表
                io.to(clientID).emit(SOCKET_ACTIONS.ADD_PEER, {
                    peerID: socket.id,
                    createOffer: false
                });
                // 新用户发送连接请求
                socket.emit(SOCKET_ACTIONS.ADD_PEER, {
                    peerID: clientID,
                    createOffer: true
                });
            });
            socket.join(roomID); // 加入房间
        });
        // 其他Socket操作
    });
    app.use.....
});

疑问

  • 如何正确配置Socket.io以支持多Worker场景,确保跨进程的用户能正常交互?
  • 是否必须使用Redis?使用后会破坏现有代码吗(比如上述获取房间客户端的代码)?
  • 我尝试了如下Redis配置示例,是否正确?
const app: Express = express();
const server: http.Server = http.createServer(app);
const sockets = require('socket.io');
const redis = require('socket.io-redis');
const bindListeners = (io) => {
   io.on('connection', socket => {
       // 之前的代码
   });
}
const io = sockets(server, {
    transports: ['websocket']
});
io.adapter(redis({host: 'localhost', port: 6379})); // 我想使用socket.io-redis@5.2.0
bindListeners(io);
nextApp.prepare().then(() => {...next app所有逻辑...});
  • 负载均衡器应如何转发Socket流量?

额外尝试的问题

我试过Socket.io官方PM2方案,代码如下:

const nextApp = next({ dev: config.dev });
const app: Express = express();
const server: http.Server = http.createServer(app);
const io = require('socket.io')(server, {});
io.adapter(createAdapter());
setupWorker(io);
io.on('connection', socket => socketServer(socket, io));
// socketServer
export default (socket, io) => {
    console.log('Socket connected, ID: ', socket.id);
    // 和之前相同的代码
}

但出现4个PM2进程对应4个IO实例的问题,导致无法获取房间客户端,socket.broadcast.emit也无法正常工作。

内容的提问来源于stack exchange,提问作者Roman Nozhenko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 19:16:37