2017-06-12 125 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