2012-04-13 46 views
2

我曾經被告知GAE是無狀態的。我一般理解無國籍的概念,但我可以在概念上將它用於GAE型系統。GAE是無狀態的嗎?什麼影響?

我特意問這個問題,因爲我開發的應用似乎有干擾問題。也就是說,當兩個或兩個以上的人同時使用它時,它會變得混亂。 (我繼續錯誤地測試以確認錯誤只發生在同時使用中)。我發現有兩種方式理論上會發生這樣的干擾:A,錯誤的GQL查詢獲取錯誤的db記錄(我檢查了這一點,不)。或者b。在服務器級別。我的問題:後者實際上可能嗎?當應用程序正在投放時,一個用戶是否可以通過改變程序內某個變量的狀態來干擾另一個用戶?或者,這也許是無國籍人阻止的嗎?我很困惑,可能錯誤地提出了這個問題。合十禮。

+1

如果沒有更多詳細信息,則無法診斷。你能向我們展示一些重現問題的代碼嗎?在你對Rick答案的評論中,你提到你正在使用像'userData'這樣的全局變量。你不能那樣做,因爲a)多個用戶將使用你的應用程序的同一個實例,並且b)同一個用戶將使用你的應用程序的多個實例。 – 2012-04-18 00:28:14

回答

3

GAE仍然運行(虛擬?)服務器來處理HTTP請求。服務器實例可能會啓動,處理一些請求並關閉。在任何時候,大量的服務器實例可能都在運行。兩個連續的HTTP請求可能最終由相同的服務器實例或單獨的服務器實例提供服務。您需要將您的軟件設計爲無狀態,因爲您不知道運行哪個服務器實例。

但是,由於GAE仍在運行虛擬服務器,因此您可以設置某種全局靜態變量,該變量可以在給定服務器實例上的多個HTTP請求之間進行修改和訪問。很可能你已經做了一些事情。

此狀態通常沒有用處,因爲如前所述,您無法保證後續的HTTP請求會碰到相同的服務器實例,或者關閉服務器實例時的任何控制。但是,例如,如果您想針對每個服務器實例平均請求的請求數進行實驗,則可能會這樣做。

+0

你讓我接近我需要理解的東西。請詳細說明:每個用戶將在每個使用會話中發送很多HTTP請求。如果每個用戶不是由一致的(虛擬)服務器處理的,那麼變量狀態如何保存?例如,我創建了一個類userData()的python對象 - 如果服務器實例不斷變化,那麼存儲的方式和位置在哪裏? – cognitiveUpgrade 2012-04-13 18:32:33

+0

如果userData是任意的python類,那麼它只是在運行的服務器實例上實例化。根據變量的範圍,它可能會或可能不會經歷多個請求。無論是哪種情況,你都不想使用它。您想要將數據存儲在數據存儲中,因此userData應該來自ndb.Models,並且可以將其存儲在數據存儲中。數據存儲在所有服務器實例之間共享,因此從數據存儲中獲取的數據將是「全局」的。儘管如此,您確實需要使用事務來同步數據存儲訪問。 – dragonx 2012-04-13 22:45:45

+0

哦,如果你使用的是memcache,你需要知道memcache數據可以在任何時候被清除。顧名思義它就是一個緩存,你需要一個穩定的支持數據,比如數據存儲,來存儲你的數據,以防它在memcache中不可用。 – dragonx 2012-04-13 22:50:08

5

我認爲你混淆了一些術語。首先,你使用什麼語言?這是Java還是Python?

告訴你GAE是「無狀態」的人不知道他們在說什麼,否則你對他們告訴你的事情感到困惑。 GAE是一個Web服務器平臺,您的應用程序的狀態取決於您。 HTTP是一種無狀態協議(GAE用於構建使用http的Web應用程序),但您可以絕對打開會話並以這種方式實現用戶的狀態。

您正在描述的錯誤情況是併發性之一。您在GAE(數據存儲,memcache等)中共享資源,並且如果使用高複製數據存儲,則在數據存儲中也具有最終一致性。

GAE並不保證同一個服務器實例會提供同一個人的多個請求,並且默認情況下不存在多線程(反正在java中,我不確定python)。在沒有多線程的情況下,在任何時候只有一個人在任何情況下。但是,如果啓用多線程,則必須確保代碼是線程安全的,否則您可以讓2個用戶在單個實例上修改變量,但這不僅適用於GAE。

您肯定可以擁有2個用戶修改2個不同服務器上的相同數據存儲區實體或相同的memcache條目,並且您需要使用事務等爲該情況編寫代碼。另外,最終一致性可能會在寫入和一個閱讀,所以如果你寫數據和其他用戶立即讀取它們,他們可能不會得到相同的價值 回來。

+0

+1 HTTP是一個無狀態協議 – 2012-04-13 18:39:02

+0

我使用Python,高複製。我將調查多線程,但我沒有啓用任何此類選項。我懷疑我的用戶正在修改相同的數據存儲條目,因爲每個數據存儲條目都包含一個userId列,並且用戶只能訪問/修改他們自己的記錄。但是我肯定可以用Memcache(我不太明白)這麼做。我的python全局對象被命名爲'userData'。也許他們互相覆蓋,我需要給他們命名爲'user'。userId.userData'來避免衝突? – cognitiveUpgrade 2012-04-13 18:41:33

+0

如果您正在使用memcache,則需要考慮共享所有數據,並且兩個用戶可以絕對覆蓋這些值。 – 2012-04-13 18:52:35

2

上的「無國籍」幾備註:在本身

  1. HTTP協議是無狀態的,即請求不依賴於彼此(=不需要在一些預定義的順序來調用)。

  2. Web應用程序通常是有狀態的。他們通過保存數據並基於該數據強制/限制某些動作來實現這一點,例如,用戶登錄。

  3. 數據可以以多種方式保存在Web服務器上:數據庫,緩存,內存。用於保存用戶數據/狀態的一種標準方式是servlet sessions

  4. 當人們說App Engine是無狀態的時,他們通常會提到前端實例沒有自己的永久存儲(即可寫文件系統)這一事實。要在前端實例上保存狀態代碼,必須使用Google API之一:數據存儲區,memcache等。

+0

謝謝。我認爲我的問題並不瞭解memcache的性質。一旦我解決了問題,我會更新這個問題。 – cognitiveUpgrade 2012-04-13 21:11:57