论坛首页 Java企业应用论坛

ASP模式应用中多客户数据管理方案探讨

浏览 5467 次
该帖已经被评为良好帖
作者 正文
   发表时间:2006-10-21  
ASP(Application Service Provider)模式应用与普通应用之间的一个重要差别是ASP系统需要管理多个客户的数据。不同客户之间的数据完全独立,没有关联。不允许一个客户查询另一个客户的数据。即使多个客户共享一个数据库,对单个客户来说,其它客户的数据可以看作是不存在的。 这里主要讨论在J2EE应用中如何解决这个问题。当然,这里讨论的方法对于其它架构的系统可能也适用。

方案1:单数据源,单套表。
所有客户的数据都存放在一个数据库的同一套表中, 在部分表中增加标示字段,表明该记录是属于哪个客户的。具体哪些表中要增加标示字段当然要看具体应用,不过我觉得可能大部分表示实体对象的表中都需要加。在很多查询条件中都需要包括这个标示字段。即使是用户自定义的查询,系统也需要在查询条件中加入该字段。

优点:数据源和数据库的管理都比较简单。数据源管理方面和普通的J2EE应用没有差别。

缺点:增加程序的复杂性。如果应用比较复杂,很多数据表都需要加入客户表示字段,很多查询都需要包括该字段,会比较麻烦。如果有遗漏,特别是查询条件中遗漏该字段,就会造成一个客户看到另一个客户的数据。另外,需要在系统的安全性方面做比较细致的设计。比如,某个功能通过在URL中包含某个实体的关键字以查询该实体的信息,或对该实体进行操作。在普通应用中后台只需要根据关键字查出该实体即可。但是在ASP应用中,就必须额外判定该实体是否属于当前登录用户,或者要在查询中条件中加入客户标示。当然如果有办法自动完成这样的检查或者自动修改发到数据库的查询条件,这个缺点就可以避免。只是我现在还没有想到这样做的好方法。

-------------------------------------
方案2:多套表,多数据源

数据库中每个客户一套表。可以是MySql, PostgresSQL, SQLServer中的不同数据库,或者Oracle中的不同schema。在应用服务器中配制不同的数据源,或者使用不同的连接池。 在访问数据库,需要得到数据库连接时,根据当前用户所属的客户选择合适的数据源或者连接池。

优点:不同客户的数据物理分离,安全性比较好。除了获取数据库连接部分的程序以外,其它程序和普通应用没有两样。不同客户的数据可以放置在不同的数据库服务器中,分担数据库服务器的负荷。

缺点:数据库连接的利用效率不高。ASP模式的主要客户是中小企业。这样带来的结果是客户数可能会很多,但是单个客户的用户数和并发登录数都不会太多。在系统这边来说,则是数据源或连接池很多,但每一个的利用效率都不高。在数据库服务器这边仍然会有很多连接,因为每个数据源或连接池都需要保持一定数量的可用连接。这样通过连接池共享数据库连接而减少总连接数的好处被大大削弱了。

另一个缺点是如果需要增加客户时,需要在应用服务器中配制新的数据源,或者修改应用自己的数据库连接池配制。某些情况下可能无法作到在应用不中断的情况下使这些配制生效。

------------------------------------
方案3:多套表,多Schema,单数据源。

这个方案基本是方案2的变种。很多数据库提供Schema,比如PostgresSQL中,同一个数据库下可以有多个Schema,Oracle中,每个用户就是一个Schema。即使用同一个用户登录数据库,只要在表名前加上schema名字,就能访问不同schema中的表。不同客户的数据就可以存放在不同的schema中。这样就能用同一个数据源或连接池,只是在所有的表名前要根据当前用户加上合适的shcema名字。如果要程序员自己这么做当然是很麻烦的。但如果用Hibernate就方便了。因为Hibernate中可以配制default schema,Hibernate在生成SQL时会自动在表名前加上schema名字。

因此如果使用Hibernate实现该方案就需要多个SessionFactory,每个客户对应一个SessionFactory。除了default schema以外,这些SessionFactory的配置完全一样。当程序需要SessionFactory的时候,需要有一个分配程序根据当前用户选择合适的SessionFactory。这些SessionFactory可以在系统启动时根据配制文件全部建立好,也可以采取lazy initialize的方法,这样也能支持动态增加客户。

优点:除了方案2的优点以外,共享数据源或连接池,效率更高。

缺点:对实现手段有一定依赖性。使用Hibernate会比较容易实现,其它方式我不清楚。每个SessionFactory都会有一定开销。多个SessionFactory会增加这部分开销,增加到多少程度,对性能有多少影响还有待测试。多个SessionFactory的情况下,二级缓存会否互相干扰,还是每个SessionFactory有各自自己的二级缓存也有待测试。

------------------------------------
所有以上方案都是所有客户共享同一个应用(WAR或EAR)。这种方式有一个缺点,不过这个缺点和数据源无关。如果用户可以以点菜式的方式选购不同功能,也就是说虽然不同客户共享一个应用,但是提供给他们的功能是不同的。这种情况下,程序中会有很多地方要判断用户是否可以使用某功能。这会带来另一种麻烦。这个和权限控制有类似,也许可以用Acegi之类的框架解决。但和权限控制又不完全一样。因为有时简单地提示用户他无权使用某功能可能不够友好,而需要以一种更优雅的方式提供用户降级过的系统功能。当然这个和具体应用有关,这里就不展开了。

------------------------------------
方案4:多套表,多应用

这个方案和以上方案不同,除了数据物理分离以外,应用也物理分离。每个客户有各自自己的WAR或EAR。如果使用方案3中的多Schema的方法,那么数据源可以共享,每个应用的SessionFactory有不同的default schema。

优点:应用简单。这样的应用和普通的J2EE应用没有任何区别。支持高度定制化的系统功能。每个应用基本相同,又可以有很大差别。比如用户没有选择的功能更本就不部署。

缺点:应用服务器中每个应用都会有一定的开销,占用一定的固定的内存。这个开销来自于应用服务器管理应用的数据结构;每个应用的class loader,和读入的类的字节码(应用服务器会判断出不同应用的同样名字的类具有同样的字节码,从而只保存一份吗?对次我表示高度怀疑);每个应用还可能会有自己的线程,比如任务调度线程。这些开销可能会使一个应用服务器能部署的应用不会太多(和ASP模式的潜在客户数比较),从而在客户数比较大的情况下需要增加应用服务器的数目。
   发表时间:2006-10-21  
分析的挺细致的,暂。
我们现在用的是方案二,这个方案在开发和部署方面都没有问题,只要你别把针对不同企业的数据源配置文件部署到classes目录下,在新增企业用户的时候就不用中断应用了。
数据库连接占用问题,你只要把不活动线程的生存时间尽量设置小一点,那么问题也不大的。因此我推荐的是方案二。

至于方案三,你提到需要为每个客户配置SessionFactory,这样的话,岂不是增加客户时,需要中断应用了。不大好吧。

0 请登录后投票
   发表时间:2006-10-22  
hexiaodong 写道
分析的挺细致的,暂。
我们现在用的是方案二,这个方案在开发和部署方面都没有问题,只要你别把针对不同企业的数据源配置文件部署到classes目录下,在新增企业用户的时候就不用中断应用了。
数据库连接占用问题,你只要把不活动线程的生存时间尽量设置小一点,那么问题也不大的。因此我推荐的是方案二。

至于方案三,你提到需要为每个客户配置SessionFactory,这样的话,岂不是增加客户时,需要中断应用了。不大好吧。

每个数据源或连接池中是否至少要有一个活动连接?否则每次用户申请时再建立连接速度就太慢了。这样对数据库来说活动连接的数目不会少于数据源或连接池的数目,也就是不会少于客户数。对性能有多大影响就看你有多少客户了。

SessionFactory可以动态生成的。因为所有的SessionFactory的配置基本是一样的,只是default schema不同。最简单的就用客户好作为schema name,那增加客户时就没有什么需要额外配置的了。
0 请登录后投票
   发表时间:2006-10-22  
我正在使用Plan2,担心的就是这个多数据源。应用程序使用iBATIS,现在只能以DBCP配置实现,在小客户量的情况下,问题不是很大,但数据库连接数、连接池效率在30个客户以上时,会有性能问题。我使用PostgreSQL,最大25并发连接,单台Solaris 10 x86服务器。连接池再配置的小一些,仔细地调整每一个客户的实际情况,可在单台机器上实现可以接受的性能,超过一定性能要求时,增加服务器肯定是必须的。
0 请登录后投票
   发表时间:2006-10-23  
如果采用方案二,我觉得使用离散式数据库更为合适。
比如firebird。可以为每个应用,创建一个单独的gdb文件。这样在创建数据库连接、备份还原、数据库安全、客户定制方面,都非常方便。唯一不太爽的是,firebird的索引性能,不如oracle/sqlserver。在单表数据上百万时,分页速度(比oracle/sqlserver)会慢一些
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics