2013-04-18 30 views
0

有一個沒有具體解決方案的類似線程,我認爲最好開始一個新的。如何將單用戶WebApp擴展到多個用戶

我面臨的一個情況我有一個Web應用程序樹脂託管(就像Tomcat的我猜的)。到目前爲止,我一直在使用db4o開發應用程序,因爲我一個人,我需要儘快完成應用程序,我有一個數據庫的用戶和另一個數據庫爲單個用戶(我)的應用程序數據,現在該應用程序幾乎完成我即將轉向postgresql,並且我正在認真考慮每個用戶的數據庫,即使數據庫爲多個應用程序保存數據,因爲它會處理一些機密數據,我認爲單獨的數據庫將是最好的(安全方面)。已經有一個基本的會話管理,在瀏覽器中存儲用戶數據,如ID。但我想知道如何將它擴展到多個用戶/分貝。

我想擴大監聽器類,保持情境數據以正確的db對象傳遞給應用程序實例,或可能設定爲目的的過濾器。

.UPDATE。

我想給我一些更多的見解,我目前有什麼。

我有:保存到某些對象的引用

上下文,這些對象中的一個連接到DB併爲用戶和密碼檢查。

演示的servlet(HttpServlet的)映射爲 「/」,其具有的登錄形式POST到/登錄。

映射到「/ login」的登錄servlet(HttpServlet),它檢查httpSession用戶密碼屬性是否針對Context中所駐留的相應對象,如果有匹配則設置保存USERID並將用戶重定向到的httpSession屬性應用程序本身位於/index-debug.html,如果不是,它會再次創建一個帶有登錄表單的新頁面。

映射到/index-debug.html的授權和驗證過濾器驗證用於USERID屬性的httpServletRequest,並檢查用戶是否有權訪問該應用程序。

最後是一個負責讀寫webApp用戶數據數據庫的數據庫bean。當我在webApp中執行某種方法時,CP2JAVAWS將該方法與該bean中的相應方法進行匹配,問題是此bean具有靜態數據庫,並且迄今爲止它只允許一個用戶。

我想要做的就是以某種方式讓這個DB豆到每個用戶實例化一次,讀取和存儲根據當前登錄用戶的相應數據。

每個用戶一個數據庫的想法目前已被丟棄,但我不知道該如何解決這個問題。

回答

1

您提到Postgres作爲數據庫後端,並具有稱爲模式的功能。這是在數據庫中有一個物理數據庫和多個模式的地方。我的經驗來自Rails,但概念是相同的。這種方法避免了將人們的數據混合在同一組表中,這聽起來像是您最關心的問題。我知道你在使用Java,但watch this talk on Multi-tenant apps in Rails to get a background from Guy Naor這是如何工作的,取捨等

下面是一些具體的步驟,讓你開始使用下來的Pos​​tgres模式的路徑選擇:

  1. 有Postgres中的默認模式。這將是您放置用戶身份驗證表和任何其他關於用戶登錄等的通用元數據表的地方。See Postgres docs for more info on how schemas work
  2. 爲您創建的每個模式(例如user_001,user_002等)提出一個命名約定。 。在所有表設置時預分配一堆空模式,並且當用戶第一次註冊或登錄時,可以爲它們分配一個模式,並將模式名稱存儲在其公用模式和用戶對象中的用戶記錄中你有在HttpSession中。不需要爲首次使用的用戶運行表格創建腳本 - 這將成爲Web應用程序中的性能拖動。你只需要保持領先新用戶的比例。例如,你可以有一堆空user_standby_1的... user_standby_100模式,然後當有人或註銷登記,你可以運行這個SQL:

    myquery = "ALTER SCHEMA user_standby_? RENAME TO user_?"; myquery.setString(1,standby_id); myquery.setString(2,user_id);

  3. 當您創建數據庫的bean(使用超對於這一點,見下文),從HttpSession的用戶對象的架構名稱通過,則每一次操作之前執行此SQL將它們隔離到只有他們的架構:

    myquery2 = "SET search_path TO ?";
    myquery2.setString(1,user.search_path);

  4. 如果你有一個空完整的公共架構,那麼你希望在搜索路徑中忽略公共,否則你將在搜索路徑中有兩個同名的表。如果您希望用戶搜索路徑包含SET search_path TO user_001,public,那麼在創建表之後,將所有數據表從公共用戶以及您需要的任何元信息中刪除。

  5. 對於維護,編寫一個腳本,您可以通過命令行運行以刪除空的user_standby模式,創建新的user_standby模式,並對Rails Migrations for Java進行等效的次表更改。
  6. 對於大型維護活動,可能最好創建新的模式,例如, user_v2_001,然後編寫腳本來遷移其中的數據。這取決於對錶格進行的更改有多複雜。

如果你走另一條路線,並有一組表的所有用戶數據,那麼最好的方法是在每已經user_id說明,寫你的SQL使用該時間。如果您使用傳統的規範化並進行連接以獲取您的user_id,那麼最好確保您不會錯過連接,否則用戶將開始看到其他數據。

Postgres模式功能允許您鎖定用戶只能訪問他們自己的數據。在弄清楚基本知識之後,使用Java中的超類來編寫上面的第3步,以便每個MyTableDBBean都從MasterDBBean擴展並使用超類構造函數將搜索路徑與用戶的模式分離。然後,在代碼中只有1個地方完成了這個任務,並且您不必記住每個表或查詢除了業務邏輯以外的任何事情。

+0

非常感謝,它基本上補充了ryan1234所做的答案。謝謝你們倆。 – Jigzat 2013-04-30 17:20:21

2

樹脂!我在一段時間內還沒有聽說過Resin的工作。 =)

我見過有每拿出經常對堆棧溢出的系統的用戶一個數據庫的想法。反應是一樣的 - 這不是一個好主意。

有很多的原因,但是我就堅持規模,可維護性和波動。

規模

有些數據庫對他們能有多少數據庫有很大的侷限性。我不知道單個Postgres實例可以擁有多少個數據庫。

此鏈接(https://dba.stackexchange.com/questions/23971/maximum-number-of-databases-for-single-instance-of-postgresql-9)表示有人在一個實例上獲得了10,000個數據庫。

我想說隨着時間的推移,一個網站有一百萬用戶(當然不是所有的活動)都是不常見的。換句話說,我敢打賭,你的用戶數會在某個時間點打破Postgres,每個用戶有一個數據庫。

可維護性

假設您只想10,000個用戶,因此可以使萬個數據庫。當你想更新每個數據庫中的表時會發生什麼?將這些更改推出是很痛苦的。

通常會發生的情況是,您將編寫一個腳本來觸摸每個數據庫,即使您已經測試了腳本,但在腳本中途死亡,現在您在一個狀態中停留了一半絕望的分鐘,一半在其他一些州。

或者更糟糕的是某種數據庫不同步並且與其餘數據庫有不同的模式。現在您可能擁有多個「用戶」數據庫的實時版本。

波動

用戶是善變的。他們會在今天註冊,然後再也不會回來。他們會註冊並在兩年後再次登錄。他們會因爲忘記密碼而創建多個帳戶。

這會很快導致孤立的數據庫。您需要(或希望)編寫腳本來定期清理它們。

當創建數據庫時,一些更現代的數據庫(如MongoDB和Couchbase)實際上預先分配大部分磁盤/內存。我不相信Postgres會這樣做,但這是需要考慮的事情。

安全

如果有人黑客你的Postgres中,分離由數據庫的用戶是不會幫你的。它們可以在數據庫之間移動,就像在表格中的記錄之間移動一樣簡單。最好鎖定數據庫機器,然後讓用戶一起生活在一張桌子上。擴展更容易,維護更容易,並且可以管理波動性。

+0

謝謝!!,是的,數據庫每用戶的主題在堆棧溢出中被多次觸及,您的回答是第一個讓我確信不這樣做,但仍然如何擴展我的webApp給多個用戶?我對此的知識是非常基本的,在我的情況下,WebApp(卡布奇諾/ Objective-J)不直接查詢數據庫,基本上是通過CP2JAVAWS使用javascript遠程JAVA方法調用,因此實際的QUERY發生在服務器中,對象並將它們作爲JSON對象發送(當然這對我來說是透明的) – Jigzat 2013-04-24 01:50:36