如何在已有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
相关产品推荐
相关产品推荐

