使用 Symfony2 和 Doctrine2 开发多租户应用程序的最佳实践

2022-08-30 20:08:29

我正在开发一个需要支持多租户模型的应用程序。我正在使用symfony2 php框架和教义2。

我不确定构建此要求的最佳方法。Symfony 的 ACL 功能是否提供了解决方案的一部分?

您能提供哪些建议或想法?是否有任何示例 symfony2 应用程序或开源应用程序已实现此策略?

我的第一个想法是在所有表中使用tenant_id列,并使其与应用程序中的帐户对象相关。我不确定ACL是否应该处理我想要做的事情,或者你是否仍然负责针对你的对象的所有查询,以便它们不会返回未经授权的数据。

如果我没有使用教义,可能很容易说只是附加到每个查询,但我不确定这是正确的方法。Where tenant_id = @accountid

谢谢


答案 1

我们已经这样做了一段时间(虽然不是symfony和教义,但问题保持不变) - 我们从一个巨大的数据库开始,并在每个表中每行实现一个“环境标识符”。通过这种方式,架构迁移很容易:所有代码都是统一的,因此架构更改是对代码和架构的单个更改。

然而,这导致了速度(大表),敏捷性(移动/备份等大型数据集比许多较小的数据集更密集)的问题,当然还有更容易分解的环境,因为单个故障会拉下系统中的每个数据集...

然后,我们切换到多个数据库;每个环境都有自己的架构。通过利用 Doctrine 提供的迁移(在本例中为 1),我们能够快速更新整个应用或仅更新单个环境。此外,在触角之间移动特定变化的能力允许在速度和优化方面具有更高的精度。

我的建议是:创建一个扩展到不同租户的单个核心,并保持每个试点的本地自定义数据库配置。(在类似应用程序.ini结构中)

/
    apps/
        tentant1/
            models/ <--- specific to the tenant
            libraries/ <--- specific to the tenant
            config/
                app.ini <--- specific configuration
        tentant2/
        /**/ etc
    core/
        models/ <--- system wide models
        libraries/ <--- system wide libraries (i.e. doctrine)
        core.ini <--- system wide configuration

这可以使一切井井有条。我们甚至拥有每个试探者可用的核心的复杂结构。因此,能够覆盖特定于租户的“核心”的各个方面。


答案 2

我们通过工作中的主要解决方案之一来做到这一点,这当然是可能的。我们使用 Symfony2 的捆绑包来创建一个“基本”捆绑包,然后由其他每个客户端的捆绑包进行扩展。

也就是说,我们正在考虑在未来摆脱这种方式。对我们来说,采用多租户的决定并不是正确的,因为我们的许多客户都对他们的数据与其他所有人的数据位于同一数据库表中感到不舒服。这完全不在于随着表的增长而导致性能缓慢的潜在问题。

我们还发现,教义2有一些非常严重的问题,除非它得到很好的控制。虽然这可能是结构不良的代码和数据库逻辑的副作用,但我觉得ORM能够达到它抛出致命错误的地步是一个漏洞,因为它使用了太多的内存 - 特别是当它使用这么多内存的唯一原因是因为它正在批处理SQL查询以便它们可以“更有效”。

这纯粹是我的观点,当然:)对我们不起作用的东西可能很适合您,但我确实觉得您最好为每个客户端保留单独的数据库,即使它们都存储在同一台服务器上。


推荐