2017-06-12 127 views
0

我们正在Android和IOS中实施游戏。在游戏结束时,每个客户都会调用一个API来完成游戏。它看起来像如下:仅处理多个并发Web API请求中的一个

/game/finish 

有这样一个JSON一起:

{ GameId:1, WinnerId: 2, .... } 

为了确保完成总是被调用,双方球员调用这个API使用相同的参数。因此,这些请求可能会在服务器上同时收到。在服务器端,我们应该只处理这些并发请求,并放弃另一个请求(为了增加/减少正确的赢家/输家点数和其他业务)。

服务器端是用C#实现的WebAPI

我使用的lock语句思维,但它可能会影响性能。

任何帮助,让我成为一个更好的解决方案会更明显。

+0

如果只有获胜者发送请求,怎么样? – Oscar

+0

请确保只有一个客户端发送请求或将游戏标记为已解决,当您进行API调用时只需检查是否已处理游戏,例如完了。 ('if(!isGameHandled(gameID)){//处理并保存状态}') – jAC

+0

因此,如果Winner网络连接在游戏结束时丢失,会发生什么?我们将失去那场比赛@Oscar。这就是为什么我们强迫两个客户打电话完成 – Nasseh

回答

1

您需要使用lock,实际上有很多方法可以做到这一点使用lock,正确的方法取决于许多建筑的问题。它可以在数据库级别,后端级别或简单地在前端(webAPI)级别完成。
它也可以在“ - 分配 - 解锁 - 锁定完成”来完成的方式,如果你的游戏整理过程可能会持续太长时间,从而使第二用户不会等待答复太长。

你可以简单地使用并发字典存储锁和使用双重检查锁定,以尽量减少lock S,但有些人认为它是一个反模式。
在你的情况下,谁提交的结果将采取锁和第一玩家完成游戏:

private readonly ConcurrentDictionary<int, object> _gameLocks = new ConcurrentDictionary<int, object>(); 

// Finish process: 
if (!GameIsFinished(gameId)) 
{  
    lock (_gameLocks.GetOrAdd(gameId, new object()) 
    { 
     if (!GameIsFinished(gameId)) { 
      FinishGame(gameId); 
     } 
    } 
} 

即使第二线穿过第一检查(在竞争条件的情况下),那么它会等待直到第一次完成整理过程,然后检查GameIsFinished等于true并且什么都不做。

我只是有几个问题,你的设计:

  1. 什么如果两个用户在完成之前关闭该窗口?游戏是否被忽略和遗忘?
  2. 如果用户用自己的winnerId更换您的请求,并有两个请求与相同的游戏ID,但不同的WinnerId
  3. ,如果我刚才的垃圾邮件与比赛不同的结果,您的服务器,实际上从来没有玩过吗?

你的服务器应该肯定决定谁是赢家,而不是客户。

+0

这里是答案: 1. \t有一个政策,如果一个玩家离开游戏,第二个玩家是赢家。 2. \t你是对的,他们可以。但我们是一个团队,并且我确信这两个客户都能正确设置赢家 3. \t对此没有回答:) 我们使用Socket IO进行实时游戏,服务器端是nodeJS。我们无法在nodeJs中处理这个问题,因为我们对它不熟悉 – Nasseh

+0

“交叉手指解决方案”(可能,但我相信它永远不会发生)是万恶之源。但是这个答案也显示了这样一个解决方案:希望没有人会提高工作进程数 –

+0

我应该提到每个球员在提交结果时都会首先进行身份验证(调用Finish Api) – Nasseh