NodeJS + Cluster + Socket.IO 如何正确创建游戏房间?
NodeJS + Cluster + Socket.IO how to create game room properly?
我正在制作一个简单的游戏引擎,它实现了房间操作。
我想了很多,但仍然怀疑我没有以正确的方式开房间。
场景如下。
1) There's one static room, where users are able to 'register'.
2) after certain number of users are registered, it should create dynamic room and put these certain number of users in that room and make them quit the static room.
因此,如果我们在多个实例中 运行 假设我们正在等待 2 个用户。
2个用户加入静态房间->创建新房间(在redis中)->让这两个玩家进入那个房间(订阅)->让那些玩家离开静态房间(类队列系统)。
现在我觉得是个问题
2个用户加入静态房间 -> 在创建新房间之前,另一个玩家加入静态房间(不同节点实例) -> 创建新房间 -> 将两个玩家移到那里 -> 另一个实例仍然认为有足够的用户创建新房间 -> 奇怪的事情发生了。
这是正确的吗?队列式房间应该如何实现?
一种解决方案是让所有未连接的玩家进入一个唯一的节点实例,该实例负责创建房间并将玩家分配到这些房间。然后,一旦他们被分配到一个给定的房间,它就会将他们重定向到负责这个房间的节点实例。
您需要原子操作:将所有这 4 个步骤放入一个事务中。使用 Redis,您可以使用 Transaction or Lua Scripting 来实现它。
使用 lua 脚本,您可以拥有这样的脚本:
-- add new user to static room
redis.call('lpush', 'static_room', ARGV[1])
-- if the number of static room reaches the limit
local num = redis.call('llen', 'static_room')
if num == 2 then
-- get the room number for a new dynamic room
local new_dynamic_room_num = redis.call('incr', 'dynamic_room');
local dynamic_room = 'dynamic_room' .. new_dynamic_room_num
-- move all users from static room to dynamic room
while true do
local num = redis.call('llen', 'static_room')
if num == 0 then break end
redis.call('rpoplpush', 'static_room', dynamic_room)
end
end
由于 lua 脚本以原子方式执行,在我们完成将所有用户从静态房间移动到动态房间之前,没有其他用户可以加入静态房间。
我正在制作一个简单的游戏引擎,它实现了房间操作。
我想了很多,但仍然怀疑我没有以正确的方式开房间。
场景如下。
1) There's one static room, where users are able to 'register'.
2) after certain number of users are registered, it should create dynamic room and put these certain number of users in that room and make them quit the static room.
因此,如果我们在多个实例中 运行 假设我们正在等待 2 个用户。
2个用户加入静态房间->创建新房间(在redis中)->让这两个玩家进入那个房间(订阅)->让那些玩家离开静态房间(类队列系统)。
现在我觉得是个问题
2个用户加入静态房间 -> 在创建新房间之前,另一个玩家加入静态房间(不同节点实例) -> 创建新房间 -> 将两个玩家移到那里 -> 另一个实例仍然认为有足够的用户创建新房间 -> 奇怪的事情发生了。
这是正确的吗?队列式房间应该如何实现?
一种解决方案是让所有未连接的玩家进入一个唯一的节点实例,该实例负责创建房间并将玩家分配到这些房间。然后,一旦他们被分配到一个给定的房间,它就会将他们重定向到负责这个房间的节点实例。
您需要原子操作:将所有这 4 个步骤放入一个事务中。使用 Redis,您可以使用 Transaction or Lua Scripting 来实现它。
使用 lua 脚本,您可以拥有这样的脚本:
-- add new user to static room
redis.call('lpush', 'static_room', ARGV[1])
-- if the number of static room reaches the limit
local num = redis.call('llen', 'static_room')
if num == 2 then
-- get the room number for a new dynamic room
local new_dynamic_room_num = redis.call('incr', 'dynamic_room');
local dynamic_room = 'dynamic_room' .. new_dynamic_room_num
-- move all users from static room to dynamic room
while true do
local num = redis.call('llen', 'static_room')
if num == 0 then break end
redis.call('rpoplpush', 'static_room', dynamic_room)
end
end
由于 lua 脚本以原子方式执行,在我们完成将所有用户从静态房间移动到动态房间之前,没有其他用户可以加入静态房间。