WebSocket房间管理时如何避免用户同时加入同一个房间?
我在用Socket.IO实现多人协作房间时遇到个问题,当两个用户几乎同时点击”加入房间”按钮,服务端会收到两次join事件。虽然客户端都收到成功回调,但服务端日志显示同一个房间ID被多次创建。
我尝试在服务端用if (!rooms.has(roomId))判断后再创建房间,但发现当两个连接几乎同时到达时,第一个连接还没把roomId加入Set,第二个连接就已经开始检查了。比如这样写:
io.on('connection', socket => {
socket.on('join', ({roomId}) => {
if (!rooms.has(roomId)) {
rooms.add(roomId);
createRoom(roomId); // 这里存在竞态条件
}
socket.join(roomId);
});
});
用setTimeout延时模拟处理耗时后问题复现率降低,但感觉这不是可靠的解决方案。应该用什么方法才能保证同一房间只被创建一次?
核心思路是用Promise链模拟锁机制,保证同一个房间的创建操作按顺序执行。代码里的关键点是roomLocks这个Map,它保存了每个房间对应的Promise。新来的请求必须等待前一个Promise完成才能继续。
复制过去试试,应该能解决你的问题。记得测试下高并发场景,看看是不是稳了。