在我的Meteor应用程序中实现基于转向的多人游戏服务器,客户端通过发布/订阅接收游戏状态,并可以调用Meteor方法sendTurn
将转弯数据发送到服务器(他们无法更新游戏国家集合直接)。
var endRound = function(gameRound) {
// check if gameRound has already ended /
// if round results have already been determined
// --> yes:
do nothing
// --> no:
// determine round results
// update collection
// create next gameRound
};
Meteor.methods({
sendTurn: function(turnParams) {
// find gameRound data
// validate turnParams against gameRound
// store turn (update "gameRound" collection object)
// have all clients sent in turns for this round?
// yes --> call "endRound"
// no --> wait for other clients to send turns
}
});
要实现时间限制,我想等待一段时间(让客户有时间调用sendTurn
),然后确定舍入结果 - 但仅在圆形结果尚未确定时在sendTurn
。
我应该如何在服务器上实现此时间限制?
我实施此方法的天真方法是致电Meteor.setTimeout(endRound, <roundTimeLimit>)
。
问题:
并发性怎么样?我假设我应该在sendTurn
和endRound
(?)中同步更新集合(没有回调),但这是否足以消除竞争条件? (阅读关于同步数据库操作的this SO question的已接受答案的第4条评论也产生,我怀疑)
在这方面,“每个请求”在我的上下文中的Meteor docs中意味着什么(由客户端方法调用和/或服务器{{1}调用的函数endRound
})?
在Meteor中,您的服务器代码在每个请求的单个线程中运行,而不是以Node的典型异步回调样式运行。
在多服务器/集群环境中,(如何)这会起作用?
答案 0 :(得分:3)
很棒的问题,它看起来比它看起来更棘手。首先,我想指出我已经在以下回购中实施了这个问题的解决方案:
https://github.com/ldworkin/meteor-prisoners-dilemma https://github.com/HarvardEconCS/turkserver-meteor
总而言之,该问题基本上具有以下属性:
sendTurn
)endRound
endRound
endRound
必须每轮执行一次,无论客户做什么现在,考虑我们必须处理的Meteor的属性:
this.unblock()
)。以下方法等待第一个。这意味着只要方法调用经过一个让步操作,Node或数据库中的值就会发生变化。这可能导致以下潜在的竞争条件(这些只是我已经修复过的,但可能还有其他竞争条件):
sendTurn
。两者都调用一个屈服操作来存储转弯数据。然后两种方法检查2个玩家是否已经轮流发送,发现是肯定的,然后endRound
运行两次。sendTurn
。在这种情况下,超时和玩家的方法都会调用endRound
,导致再次运行两次。endRound
永远不会被调用。您可以通过多种方式解决此问题,无论是在Node中还是在数据库中进行同步。
endRound
代码移到方法调用本身之外,使用其他东西来触发它。这是我采取的方法,确保只有计时器或最终玩家触发回合结束,而不是两者(使用observeChanges
参见here)。在集群环境中,您必须仅使用数据库进行同步,可能需要使用条件更新操作和原子操作符。如下所示:
var currentVal;
while(true) {
currentVal = Foo.findOne(id).val; // yields
if( Foo.update({_id: id, val: currentVal}, {$inc: {val: 1}}) > 0 ) {
// Operation went as expected
// (your code here, e.g. endRound)
break;
}
else {
// Race condition detected, try again
}
}
上述方法是原始的,可能导致高负载下的数据库性能不佳;它也没有处理计时器,但我确信你可以想出如何扩展它以更好地工作。
您可能还希望看到此timers code其他一些想法。我有时间将它扩展到你描述的完整设置。