为成熟的企业应用程序实施多租户

发布于 2024-12-06 18:09:46 字数 1095 浏览 1 评论 0原文

我的任务是使企业应用程序成为多租户。它有一个使用 SOAP Web 服务的 Java/Glassfish BLL 和一个 PostgreSQL 后端。每个租户都有自己的数据库,因此(至少在我的情况下)“多租户”意味着每个应用程序服务器支持多个数据库。

当前的单租户应用程序服务器使用从配置文件获取的连接字符串来初始化 C3P0 连接池。我的想法是,现在应用服务器为每个客户端/数据库提供一个连接池。

用户登录后,我可以通过查找其租户将其映射到正确的连接池。我的主要问题是如何做到这一点 - 当用户首次登录时,会查询后端的 User 表并提供相应的 User 对象。看来我需要知道只使用用户名来使用哪个数据库。

我唯一不错的想法是需要一个“配置”数据库 - 一个用于管理租户信息(例如连接字符串)的集中式数据库。 BLL 可以查询该数据库以获得足够的信息来初始化必要的连接池。但由于我只有一个用户名可以使用,似乎我还需要一个集中的用户名查找,换句话说,一个带有外键到租户的 UserName 表。桌子。

这就是我的设计计划开始出现问题的地方,让我产生了怀疑。现在,我将用户信息存储在两个单独的数据库中,这需要同步维护(用户添加、更新和删除)。此外,用户名现在必须是全局唯一的,而之前只需每个租户都是唯一的。

我强烈怀疑我正在重新发明轮子,或者至少有更好的架构可能。我以前从未做过这种事,我的团队中也没有人做过,因此我们很无知。不幸的是,该应用程序很少使用现有技术(例如,ORM 是自制的),因此我们的道路可能会很艰难。

我要求以下内容:

  • 对我现有设计计划的批评,以及改进或重新设计架构的建议。
  • 为该问题提供解决方案的现有技术的建议。我希望有一些东西可以在游戏后期轻松插入,尽管这可能不现实。我读过jspirit,但发现了很少的信息 - 关于它或其他框架的任何反馈都会乐于助人。

更新:该解决方案已成功实施和部署,并通过了初步测试。感谢 @mikera 提供的有用且令人放心的答案!

I've been tasked with making an enterprise application multi-tenant. It has a Java/Glassfish BLL using SOAP web services and a PostgreSQL backend. Each tenant has its own database, so (in my case at least) "multi-tenant" means supporting multiple databases per application server.

The current single-tenant appserver initializes a C3P0 connection pool with a connection string that it gets from a config file. My thinking is that now there will need to be one connection pool per client/database serviced by the appserver.

Once a user is logged in, I can map it to the right connection pool by looking up its tenant. My main issue is how to get this far - when a user is first logged in, the backend's User table is queried and the corresponding User object is served up. It seems I will need to know which database to use with only a username to work with.

My only decent idea is that there will need to be a "config" database - a centralized database for managing tenant information such as connection strings. The BLL can query this database for enough information to initialize the necessary connection pools. But since I only have a username to work with, it seems I would need a centralized username lookup as well, in other words a UserName table with a foreign key to the Tenant table.

This is where my design plan starts to smell, giving me doubts. Now I would have user information in two separate databases, which would need to be maintained synchronously (user additions, updates, and deletions). Additionally, usernames would now have to be globally unique, whereas before they only needed to be unique per tenant.

I strongly suspect I'm reinventing the wheel, or that there is at least a better architecture possible. I have never done this kind of thing before, nor has anyone on my team, hence our ignorance. Unfortunately the application makes little use of existing technologies (the ORM was home-rolled for example), so our path may be a hard one.

I'm asking for the following:

  • Criticism of my existing design plan, and suggestions for improving or reworking the architecture.
  • Recommendations of existing technologies that provide a solution to this issue. I'm hoping for something that can be easily plugged in late in the game, though this may be unrealistic. I've read about jspirit, but have found little information on it - any feedback on it or other frameworks will be helpful.

UPDATE: The solution has been successfully implemented and deployed, and has passed initial testing. Thanks to @mikera for his helpful and reassuring answer!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

善良天后 2024-12-13 18:09:46

一些简单的想法:

  • 您肯定需要某种形式的共享用户管理索引(否则您无法将客户端登录与正确的目标数据库实例关联起来)。不过,我建议将其做得非常轻量级,并且仅将其用于初始登录。一旦您确定了这是哪个数据库,您的 User 对象仍然可以从特定于客户端的数据库中提取。
  • 您可以设置主键[clientID、用户名],这样用户名在各个客户端之间就不需要是唯一的。
  • 除了这个薄弱的用户索引层之外,我还会将大部分用户信息保留在特定于客户端的数据库中。现在重构它可能会造成太大的破坏,您应该首先让基本的多租户功能正常工作。
  • 您需要使共享索引与各个客户端数据库保持同步。但我认为这应该不会太难。您还可以使用批处理作业“测试”同步并纠正任何错误,批处理作业可以过夜运行,也可以在出现任何不同步情况时由 DBA 按需运行。我将客户端数据库视为主数据库,并使用它来按需重建共享用户索引。
  • 随着时间的推移,您可以重构以实现完全共享的用户管理层(如果您愿意,甚至最终可以完全共享客户端数据库。但请将此保存到将来的迭代......

Some quick thoughts:

  • You will definitely need some form of shared user management index (otherwise you can't associate a client login with the right target database instance). However I would suggest making this very lightweight, and only using it for initial login. Your User object can still be pulled from the client-specific database once you have determined which database this is.
  • You can make the primary key [clientID, username] so that usernames don't need to be unique across clients.
  • Apart from this thin user index layer, I would keep the majority of the user information where it is in the client-specific databases. Refactoring this right now will probably be too disruptive, you should get the basic multi-tenant capability working first.
  • You will need to keep the shared index in sync with the individual client databases. But I don't think that should be too difficult. You can also "test" the synchronisation and correct any errors with an batch job, which can be run overnight or by your DBA on demand if anything ever gets out of sync. I'd treat the client databases as the master, and use this to rebuild the shared user index on demand.
  • Over time you can refactor towards a fully shared user management layer (and even in the end fully shared client databases if you like. But save this for a future iteration.....
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文