基于Java(GWT,Spring,Hibernate)的Web应用程序的SaaS /多租户方法

27

我目前在研究如何将一个基于Java的单租户Web应用程序转换为完全成熟的SaaS式应用程序,该应用程序使用了Spring、GWT、Hibernate、Jackrabbit、Hibernate Search/Lucene等技术。

我发现一篇文章,强调以下7个方面是将单租户应用程序变成SaaS应用程序的重要改变:

  1. 应用程序必须支持多租户。
  2. 应用程序必须具有某种程度的自助注册功能。
  3. 必须有订阅/计费机制。
  4. 应用程序必须能够高效地扩展。
  5. 必须有功能来监视、配置和管理应用程序和租户。
  6. 必须有机制来支持唯一用户识别和身份验证。
  7. 必须有机制来支持每个租户的某些程度的定制。

我的问题是,是否有人使用类似于我列出的技术在SaaS/多租户应用程序中实现了上述7个方面的任何一个?在我考虑当前的路径之前,我渴望获得尽可能多的关于最佳实践的建议。

首先,我相当确定我知道如何在模型层处理多个租户。我考虑在所有表中添加租户ID,然后使用Hibernate过滤器(以及Hibernate Search的全文过滤器)根据登录用户的租户ID对所有查询进行过滤。

但是,我对性能也有一些担忧,特别是当我们的租户数量增加时。

如果您有关于如何实现这样的解决方案的建议,将不胜感激(如果这个问题有点太开放,请谅解)。

5个回答

15
我建议您设计应用程序以支持4种租户隔离类型,即为每个租户单独创建数据库、为每个租户单独创建模式、为每个租户单独创建表以及为所有租户共享表并带有租户ID。这将为您提供灵活性,随着业务的增长,可以水平分区数据库,每个数据库具有一组较小的租户,并且还可以针对某些大型租户单独使用数据库。您的一些大型租户还可能坚持认为他们的数据(数据库)应驻留在他们的设施中,而应用程序可以在云端运行。
以下是非功能性和基础架构级别功能的详尽检查清单,您在设计应用程序时可能希望考虑其中的一些功能(有些您可能不需要立即使用,但请考虑一个商业情况,如果您的竞争对手开始提供此类服务,您该如何处理)
  1. 租户级别的自定义:a)用户界面主题和标志,b)表格和网格,c)数据模型扩展和自定义字段,d)通知模板,e)拾取列表和主数据
  2. 租户级别的角色和权限创建和管理,字段级别的访问权限,数据范围策略
  3. 租户级别的模块和功能访问控制设置,以便根据订阅包启用/禁用特定模块和功能。
  4. 任务/事件/事务的计量和监视,并在超过购买配额后限制访问控制。如果您的业务模型发生变化,将来也可以计量任何新实体。
  5. 将业务规则和工作流程从代码库中外部化,并将其表示为元数据,以便您可以为每个租户组/租户自定义它们。
  6. 查询构建器,用于创建租户和特定租户添加的自定义字段的自定义报告。
  7. 租户封装和框架级别的连接字符串管理,使您的开发人员在编写查询时不必担心租户ID。
所有这些都基于我们在构建通用多租户框架方面的经验,该框架可用于任何领域或应用程序。 不幸的是,由于我们的框架基于.NET,所以您无法使用它。
但是,任何多租户SaaS产品(新的或迁移的)的工程需求都是相同的,无论您使用什么技术栈。

1
+1 你是如何处理 c) 数据模型扩展和自定义字段,以及租户封装和框架级连接字符串管理的,使得你的开发人员在编写查询时不必担心租户ID的问题。在你的框架中? - Aravind Yarram

4
你列出的所有技术对于单租户和多租户应用程序都非常普遍和合理。我认为支持SaaS的7个“事情”更多地取决于你如何使用技术,而不是使用哪些技术。听起来你已经有一个单租户应用程序在运行。因此,除非某些东西已经不能很好地工作,否则可能没有太多理由偏离那里的技术选择。但是,你的问题在其他方面相当开放,所以很难在那里提供更具体的建议。
然而,我对根据租户ID拆分数据库(以及其他内容)有一些反馈。如果你知道你最终可能会有很多租户(例如许多小型租户或更多),那么你建议的方法可能是最好的选择。但是,如果你只有较少的租户(特别是如果它们很大),则可能需要考虑每个租户一个数据库,这样它们就可以拥有自己的表空间。我的意思是安装单个数据库,并在其中多次实例化相同的模式,每个租户一个实例。
这样做有几个优点。一个是性能,正如你提到的那样。将租户ID添加到每个表中会增加磁盘访问、查询时间和代码复杂性的开销。数据库中的每个索引也需要包含租户ID。如果你不小心,你会有将数据混合在租户之间的风险(尽管Hibernate过滤器可以帮助缓解这种情况)。对于每个租户,你可以限制访问只能是正确的租户。移植你当前的应用程序可能也会更容易,你基本上只需要在某个地方早期拦截你的请求,根据URL决定租户并指向正确的数据库。备份也很容易按租户进行,特别是如果你打算允许他们下载备份。
另一方面,也有不做这样做的原因。你将有很多数据库模式要处理,并且它们必须独立更新(如果你想避免所有租户的模式更改而导致他们全部下线,则这实际上可能是一个优点,你可以逐步推出它们)。这让你可以拥有特殊情况,可以偏离将平台视为真正的多租户SaaS部署来升级所有版本,从而导致在生产中管理多个版本。最后,我听说几乎每个数据库供应商都有一个破解点,即他们支持在一个安装中的模式实例的数量(据说有些可以达到数十万)。
当然,这真的取决于你的用例。你提到了单租户,这让我相信你现在没有太多的租户,但是你确实提到要增加很多租户。我不确定你是否指的是数百个或数百万个,但无论如何,我希望这些内容能对你的考虑有所帮助。祝你好运!

0

0

对于(1):Hibernate从版本4开始支持开箱即用的多租户配置。目前支持的是基于DB的租户和基于模式的租户,使用鉴别器将所有租户保留在同一个DB中尚未得到支持。我们已经在我们的应用程序中成功地使用了这个功能(采用基于客户端的DB方法)。

对于(3):经过一些调查后,我们决定选择Braintree来实现计费。其他许多人推荐的解决方案包括:Authorize.net、Stripe、PayPal。

对于(4):我们使用了Hibernate/Spring和JBoss Cache的集群配置作为第二级缓存。如今这已经变得“常见”,使用PaaS服务(如Jelastic),您甚至可以在开箱即用时获得预配置。


这是一个旧的帖子,但我很好奇。1.您使用了DB-per-tenant还是schema-per-tenant方法?使用DB-per-tenant,您将如何管理所有客户端,例如在UI中获取所有客户端的数据。2.安全性是如何实现的,通过Spring吗? - Himalay Majumdar
据我所记,我们使用基于租户的模式(Schema-per-tenant),使用单独的数据库来管理计费、租户等。此外,一些数据在租户之间共享(共享字典),也存储在单独的数据库中。是的,我们使用Spring Security。 - Igor Romanov

0

您所描述的是一种为多个租户提供完整服务的Saas风格应用程序。有几件事情您需要决定,例如数据隔离的重要性如何?如果您正在构建医疗或金融领域的应用程序,则数据隔离是一个关键因素。

嗯,我无法回答您所有的问题,但我建议您为应用程序考虑使用基于数据库的租户方法,因为它提供了最高级别的数据隔离。

由于您正在使用Java、Spring、Hibernate堆栈,我可以帮您提供一个我编写的小型示例应用程序。这是一个可工作的示例,您可以在本地电脑上快速运行。我在这里分享了链接。请查看并告诉我是否回答了您的一些问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接