【问题标题】:SaaS / Multi-Tenancy approaches for Java-based (GWT, Spring, Hibernate) web applications基于 Java(GWT、Spring、Hibernate)的 Web 应用程序的 SaaS / 多租户方法
【发布时间】:2011-07-24 14:30:28
【问题描述】:

我目前正在考虑将使用 Spring、GWT、Hibernate、Jackrabbit、Hibernate Search / Lucene(以及其他)的基于 Java 的单租户 Web 应用程序转换为成熟的 SaaS 风格的应用程序。

我偶然发现了一篇文章,其中强调了以下 7 个“事情”,这些“事情”是对单个租户应用程序进行重要更改以使其成为 SaaS 应用程序:

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

我的问题是,是否有人使用与我列出的技术类似的技术在 SaaS/多租户应用程序中实现了上述 7 项中的任何一项?在我走上我目前正在考虑的道路之前,我渴望获得尽可能多的关于最佳方式的意见。

首先,我很确定我对如何在模型级别处理多个租户有很好的了解。我正在考虑将租户 ID 添加到我们所有的表中,然后使用 Hibernate 过滤器(和用于 Hibernate 搜索的全文过滤器)根据登录用户的租户 ID 过滤所有查询。

不过,我对性能也有一些担忧,尤其是当我们的租户数量增长得相当高时。

任何关于如何实施此类解决方案的建议将不胜感激(如果这个问题有点过于开放,我深表歉意)。

【问题讨论】:

    标签: java multi-tenant hibernate-search saas


    【解决方案1】:

    我建议您构建应用程序以支持所有 4 种类型的租户隔离,即每个租户的单独数据库、每个租户的单独架构、每个租户的单独表以及具有租户 ID 的所有租户的共享表。这将使您能够随着您的增长灵活地对数据库进行水平分区,拥有多个数据库,每个数据库都有一组较小的租户,并且还能够为一些大型租户拥有一个单独的数据库。您的一些大租户也可能坚持他们的数据(数据库)应该驻留在他们的前提下,而应用程序可以在云之外运行。

    以下是您在构建应用程序时可能需要考虑的非功能性和基础架构级功能的详尽清单(其中一些您可能不会立即需要,但请考虑您将如何处理此类问题的业务情况如果您的竞争对手开始提供它,则需要)

    1. 租户级自定义 a) UI 主题和徽标 b) 表单和网格,c) 数据模型扩展和自定义字段,d) 通知模板,e) 选择列表和主数据
    2. 租户级别创建和管理角色和权限、字段级别访问权限、数据范围策略
    3. 模块和功能的租户级别访问控制设置,以便可以根据订阅包启用/禁用特定模块和功能。
    4. 一旦超出购买的配额,任务/事件/事务的计量和监控以及访问控制的限制。如果您的业务模式发生变化,则能够在未来衡量任何新实体。
    5. 将业务规则和工作流从代码库中外部化,并将它们表示为元数据,以便您可以为每个租户组/租户自定义它们。
    6. 查询生成器,用于创建了解租户以及特定租户添加的自定义字段的自定义报告。
    7. 租户封装和框架级连接字符串管理,让您的开发人员在编写查询时不必担心租户 ID。

    所有这些都是基于我们在构建可用于任何域或应用程序的通用多租户框架方面的经验。不幸的是,您不能使用我们的框架,因为它基于 .NET

    但是,无论您使用何种技术堆栈,任何多租户 SaaS 产品(新的或迁移的)的工程需求都是相同的。

    【讨论】:

    • +1 您如何处理 c) 数据模型扩展和自定义字段,以及租户封装和框架级连接字符串管理,这样您的开发人员在编写查询时不必担心租户 ID。在你的框架中?
    【解决方案2】:

    您列出的所有技术对于单租户和多租户应用程序都非常常见且合理。我想说支持 SaaS 的 7 个“事物”更多的是取决于您如何使用这些技术,而不是使用哪种技术。听起来您已经有了一个可以工作的单租户应用程序。所以可能没有太多理由偏离那里的技术选择,除非某些东西已经不能很好地工作。不过,您的问题在其他方面是相当开放的,因此很难在此处更具体。

    我确实有一些关于按租户 ID 拆分数据库(可能还有其他内容)的反馈。如果您知道您最终可能会有很多租户(比如说数千或更多,特别是如果他们很小),那么您的建议可能是最好的。但是,如果您的租户数量较少(特别是如果他们很大),您可能需要考虑每个租户一个数据库,这样他们每个人都有自己的表空间。我的意思是单个数据库安装,其中包含相同架构的多个实例,每个租户一个。

    这可能是一个优势有几个原因。一个是你提到的性能。为每个表添加租户 ID 会增加磁盘访问、查询时间并增加代码复杂性。数据库中的每个索引也需要包含租户 ID。如果您不小心,您将面临在租户之间混合数据的额外风险(尽管 Hibernate 过滤器有助于缓解这种情况)。通过每个租户一个数据库,您可以将访问权限限制为仅正确的一个。移植您当前的应用程序也可能会容易得多,您基本上只需要尽早在某个地方拦截您的请求,以根据 URL 确定租户并指向正确的数据库。每个租户的备份也很容易,如果您打算允许他们下载备份,则特别有用。

    另一方面,有理由不这样做。您将需要处理大量数据库模式,并且必须独立更新它们(如果您想避免让所有租户因模式更改而停机,这实际上是一个优势,您可以逐步推出它们)。它让您有可能偏离将平台视为一次全部升级的真正多租户 SaaS 部署的特殊情况,从而在生产中管理多个版本。最后,我听说几乎每个数据库供应商在一次安装中支持的模式实例数量上都有一个突破点(但据说有些可能达到数十万)。

    这当然取决于您的用例。您提到了单租户,这让我相信您现在没有太多租户,但是您确实提到了越来越多的租户。我不确定您的意思是数百还是数百万,但无论哪种方式,我希望这对您的考虑有所帮助。祝你好运!

    【讨论】:

      【解决方案3】:

      没有简单的答案。我可以描述我自己的解决方案。它可以作为其他人的灵感。

      • 每个数据库的租户 (postgres)
      • 租户之间共享一个额外的数据库
      • Spring + MyBatis
      • Spring Security 身份验证

      详情请看:http://blog.trixi.cz/2012/01/multitenancy-using-spring-and-postgresql/

      【讨论】:

        【解决方案4】:

        对于 (1):Hibernate 从版本 4 开始支持开箱即用的多租户配置。 在撰写本文时,支持的是每个租户的 DB 和每个租户的模式,并且尚不支持使用鉴别器将所有租户保持在同一个 DB 中。我们已经在我们的应用程序中成功地使用了这个功能(DB-per-client 方法)。

        对于(3):经过一些调查,我们决定与 Braintree 一起实施计费。许多人推荐的另一种解决方案:Authorize.net、Stripe、PayPal。

        对于 (4):我们使用 Hibernate/Spring 和 JBoss Cache 的集群配置进行二级缓存。在这些日子里,这变得“普遍”,使用 Jelastic 之类的 PaaS 服务,您甚至可以开箱即用地对其进行预配置。

        【讨论】:

        • 这是旧线程,但我很好奇。 1.您使用的是 DB-per-tenant 还是 schema-per-tenant 的哪种方法?使用 DB-per-tenant,您将如何管理所有客户端,例如在 UI 中获取所有客户端的数据。 2. 如何通过 Spring 实现安全性?
        • 据我记得:Schema-per-tenant,我们使用单独的数据库来管理计费、租户等。此外,一些数据跨租户(共享字典)使用,并且也在单独的数据库中。是的,Spring Security。
        【解决方案5】:

        您所描述的是一个服务于多个租户的全方位服务的 Saas 风格应用程序。您必须决定一些事情,例如数据隔离有多重要?如果您正在为医疗或金融领域构建,数据隔离是一个关键因素。

        好吧,我无法回答您的所有观点,但我建议您为您的应用程序查看每个租户的数据库方法,因为它提供了最高级别的数据隔离。

        由于您使用的是 Java、Spring、Hibernate 堆栈,我可以帮助您编写一个我编写的小示例应用程序。这是一个可以在本地笔记本电脑上快速运行的工作示例。我已经分享了它here。请看一下,如果它回答了您的一些问题,请告诉我。

        【讨论】:

          猜你喜欢
          • 2020-08-01
          • 2012-07-24
          • 2017-01-07
          • 2014-07-27
          • 1970-01-01
          • 1970-01-01
          • 2012-05-17
          • 2012-04-10
          • 1970-01-01
          相关资源
          最近更新 更多