如何将单个用户WebApp扩展到多个用户

时间:2013-04-18 03:51:49

标签: web-applications resin multiple-users

有一个类似的线程没有具体的解决方案,我认为最好开始一个新的。

我面临的情况是我在RESIN中托管了WebApp(就像Tomcat一样)。到目前为止,我一直在使用db4o开发应用程序,因为我一个人,我需要尽快完成应用程序,我有一个用户数据库和另一个数据库的单个用户(我)的应用程序数据,现在该应用程序几乎完成我即将转向postgresql并且我正在认真考虑每个用户的数据库,即使数据库保存多个应用程序的数据,因为它将处理有点机密数据,我认为拥有单独的数据库将是最好的(安全明智)。已经有一个基本的会话管理,可以在浏览器中存储ID等用户数据。但我想知道如何将其扩展到多个用户/ db。

我正在考虑扩展侦听器类,以保持上下文数据将正确的db对象传递给app实例,或者为此目的设置过滤器。

.UPDATE。

我想更深入地了解我目前的情况。

我有:

包含对某些对象的引用的上下文,其中一个对象连接到数据库并检查用户和密码。

表示servlet(HttpServlet)映射到“/”,其登录表单为POST到/ login。

登录servlet(HttpServlet)映射到“/ login”,它根据上下文中的相应对象检查httpSession用户密码属性,如果匹配则设置包含USERID的httpSession属性并将用户重定向到app本身位于/index-debug.html,如果没有,它会再次创建一个带有登录表单的新html页面。

映射到/index-debug.html的授权和身份验证过滤器,用于验证httpServletRequest的USERID属性,并检查用户是否有权访问该应用。

最后一个DB bean负责读取和写入webApp用户数据DB。当我在webApp中执行某个方法CP2JAVAWS将该方法与bean中的相应方法匹配时,问题是这个bean有一个静态数据库,到目前为止它只允许一个用户。

我想做的是以某种方式允许这个DB bean为每个用户实例化一次,并根据当前登录用户读取和存储相应的数据。

每个用户一个数据库的想法目前被丢弃,但我不知道究竟是怎么回事。

2 个答案:

答案 0 :(得分:2)

树脂!我很久没有听说过Resin或者和Resin一起工作过。 =)

我已经看到了在Stack Overflow上经常出现每个系统用户一个数据库的想法。反应基本相同 - 这不是一个好主意。

原因有很多,但我只会坚持规模,可维护性和波动性。

<强>比例

某些数据库对可以拥有的数据库数量有限制。我不知道一个Postgres实例可以拥有多少个数据库。

此链接(https://dba.stackexchange.com/questions/23971/maximum-number-of-databases-for-single-instance-of-postgresql-9)表示有人在一个实例上获得了10,000个数据库。

我想说随着时间的推移,为一个网站获得一百万用户并不常见(当然并非全部活跃)。换句话说,我敢打赌你的用户数会在某个时刻打破Postgres,每个用户只有一个数据库。

<强>可维护性

假设您只需要10,000个用户,因此您可以创建10,000个数据库。如果要更新每个数据库中的表,会发生什么?滚动这些变化是痛苦的。

通常情况下你会编写一个脚本来触摸每个数据库,即使你测试了它,脚本中途死了,现在你被困了几个绝望的分钟,一半的桌子在一个状态和一半在其他一些州。

或者甚至更糟糕的是,数据库不同步并且具有与其他数据库不同的模式。现在您可能拥有多个“用户”数据库的实时版本。

<强>波幅

用户变化无常。他们今天会报名,然后再回来。两年后他们会注册然后再次登录。他们会创建多个帐户,因为他们忘记了密码。

这将很快导致孤立的数据库。您需要(或想要)编写脚本来定期清理它们。

一些更现代的数据库(如MongoDB和Couchbase)实际上在创建数据库时预先分配大部分磁盘/内存。我不相信Postgres这样做,但这是需要考虑的事情。

安全

如果有人攻击你的Postgres框,用数据库分隔用户对你没有帮助。它们可以在数据库之间移动,这可能与在表中的记录之间移动一样容易。最好是真正锁定数据库机器,然后让用户在一个表中共同生活。它更容易扩展,更易于维护,您可以管理波动性。

答案 1 :(得分:2)

您提到Postgres是数据库后端,并且具有名为schemas的功能。这是在数据库中有一个物理数据库和多个模式的地方。我对此的体验来自Rails,但概念是相同的。这种方法可以避免将人们的数据混合在同一组表中,这听起来像是您最关心的问题。我知道你正在使用Java,但watch this talk on Multi-tenant apps in Rails to get a background from Guy Naor关于它如何工作,权衡等等。

以下是一些让您开始使用Postgres模式的具体步骤:

  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中传递来自User对象的模式名称,然后在每次操作之前执行此SQL以仅将它们隔离到其模式:

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

  4. 如果您在公共场所中有一个空的完整架构,那么您希望从搜索路径中省略public,否则您将在搜索路径中拥有2个具有相同名称的表。如果您希望用户搜索路径包含SET search_path TO user_001,public,那么在创建表格之后,删除除用户以外的所有公共数据表以及您需要的任何元信息。

  5. 对于维护,编写一个脚本,您可以通过命令行运行以删除空的user_standby架构,创建新的user_standby架构并执行相应的Rails Migrations for Java以进行次要表更改。
  6. 对于大型维护活动,最好创建新的模式,例如user_v2_001,为每个用户,然后编写脚本以迁移他们的数据。这取决于更改对表的复杂程度。
  7. 如果您使用备用路由并将所有用户数据放在一组表中,那么最好的方法是在每个表中使用user_id并编写SQL以使用每个< / em>时间。如果您使用传统规范化并进行连接以获取user_id,那么您最好确保不会意外错过连接,否则用户将开始看到彼此的数据。

    Postgres架构功能允许您锁定用户仅访问自己的数据。找出基础知识后,使用Java中的超类编写上面的步骤3,以便每个MyTableDBBean从MasterDBBean扩展,并使用超类构造函数将搜索路径隔离到用户的模式。然后,在代码中只有一个位置可以完成此操作,并且您不必记住每个表或查询除了业务逻辑之外还要执行任何操作。