适用于基于 Java(GWT、Spring、Hibernate)的 Web 应用程序的 SaaS/多租户方法
我目前正在考虑将使用 Spring、GWT、Hibernate、Jackrabbit、Hibernate Search / Lucene(以及其他)的基于 Java 的单租户 Web 应用程序转换为成熟的 SaaS 风格应用程序。
我偶然发现了一篇文章,其中强调了以下 7 个“事项”,作为对单租户应用程序进行重要更改以使其成为 SaaS 应用程序:
- 应用程序必须支持多租户。
- 该应用程序必须具有一定程度的自助注册功能。
- 必须有适当的订阅/计费机制。
- 应用程序必须能够有效地扩展。
- 必须有适当的功能来监视、配置和管理应用程序和租户。
- 必须有一种机制来支持唯一的用户识别和身份验证。
- 必须有一种机制来支持每个租户的某种程度的定制。
我的问题是,是否有人使用与我列出的类似技术在 SaaS/多租户应用程序中实现上述 7 件事中的任何一个?在我走上我目前正在考虑的道路之前,我渴望获得尽可能多的关于最佳方法的意见。
首先,我非常确定我能够很好地掌握如何在模型级别处理多个租户。我正在考虑向所有表中添加一个租户 ID,然后使用 Hibernate 过滤器(以及用于 Hibernate 搜索的全文过滤器)根据登录用户的租户 ID 进行所有查询的过滤。
然而,我确实对性能也有一些担忧,尤其是当我们的租户数量增长得相当高时。
任何有关如何实施此类解决方案的建议将不胜感激(如果这个问题有点过于开放,我深表歉意)。
I am currently looking into converting a single-tenant Java based web-app that uses Spring, GWT, Hibernate, Jackrabbit, Hibernate Search / Lucene (among others) into a fully fledged SaaS style app.
I stumbled across an article that highlights the following 7 "things" as important changes to make to a single tenant app to make it an SaaS app:
- The application must support multi-tenancy.
- The application must have some level of self-service sign-up.
- There must be a subscription/billing mechanism in place.
- The application must be able to scale efficiently.
- There must be functions in place to monitor, configure, and manage the application and tenants.
- There must be a mechanism in place to support unique user identification and authentication.
- There must be a mechanism in place to support some level of customization for each tenant.
My question is has anyone implemented any of the above 7 things in a SaaS /multi-tenant app using similar technologies to those that I have listed? I am keen to get as much input regarding the best ways to do so before I go down the path that I am currently considering.
As a start I am quite sure that I have a good handle on how to handle multiple tenants at a model level. I am thinking of adding a tenant ID to all of our tables and then using a Hibernate filter (and a Full Text Filter for Hibernate Search) to filter based on the logged on user's tenant ID for all queries.
I do however have some concerns around performance as well especially when our number of tenants grows quite high.
Any suggestions on how to implement such a solution will be greatly appreciated (and I apologise if this question is a bit too open-ended).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我建议您构建应用程序以支持所有 4 种类型的租户隔离,即每个租户的单独数据库、每个租户的单独架构、每个租户的单独表以及具有租户 ID 的所有租户的共享表。这将使您能够随着数据库的增长灵活地水平分区,拥有多个数据库,每个数据库都有一组较小的租户,并且还能够为一些大型租户拥有单独的数据库。您的一些大租户也可能坚持要求他们的数据(数据库)应驻留在他们的场所,而应用程序可以在云外运行。
以下是您在构建应用程序时可能需要考虑的非功能性和基础设施级功能的详尽检查列表(其中一些您可能不会立即需要,但请考虑一下业务情况,如果您的竞争开始提供)
所有这些都是基于我们构建可用于任何领域或应用程序的通用多租户框架的经验。不幸的是,您无法使用我们的框架,因为它基于 .NET。
但是,无论您使用何种技术堆栈,任何多租户 SaaS 产品(新的或迁移的)的工程需求都是相同的。
I would recommend that you architect your application to support all the 4 types of tenant isolation namely separate database for each tenant, separate schema for each tenant, separate table for each tenant and shared table for all tenants with a tenant ID. This will give you the flexibility to horizontally partition your database as you grow, having multiple databases each having a group of smaller tenants and also the ability to have a separate database for some large tenants. Some of your large tenants could also insist that their data (database) should reside in their premise, while the application can run off the cloud.
Here is an exaustive check list of non-functional and infrastructure level features that you may want to consider while architecting your application (some of them you may not need immediately, but think of a business situation of how you will handle such a need if your competition starts offering it)
All these are based on our experience in building a general purpose multi-tenant framework that can be used for any domain or application. Unfortunately, you cannot use our framework as it is based on .NET
But the engineering needs of any multi-tenant SaaS product (new or migrated) are the same irrespective of the technology stack that you use.
您列出的所有技术对于单租户和多租户应用程序来说都是非常常见且合理的。我想说,支持 SaaS 的 7 个“事物”更多的是取决于您如何使用这些技术,而不是技术。听起来您已经有了一个可以运行的单租户应用程序。因此,可能没有太多理由偏离那里的技术选择,除非某些东西已经运行得不太好。不过,你的问题在其他方面是相当开放的,所以很难说得更具体。
不过,我确实有一些关于按租户 ID 拆分数据库(可能还有其他内容)的反馈。如果您知道您最终可能会有很多租户(例如数千或更多,特别是如果它们很小),那么您的建议可能是最好的。但是,如果您的租户数量较少(特别是规模较大时),您可能需要考虑每个租户一个数据库,以便每个租户都有自己的表空间。我的意思是单个数据库安装,其中包含相同模式的多个实例,每个租户一个。
这可以成为一个优势有几个原因。一是你提到的性能。向每个表添加租户 ID 会增加磁盘访问和查询时间的开销,并增加代码复杂性。数据库中的每个索引还需要包含租户 ID。如果您不小心,您会面临在租户之间混合数据的额外风险(尽管 Hibernate 过滤器将有助于减轻这种风险)。通过每个租户一个数据库,您可以将访问限制为仅正确的数据库。移植当前的应用程序可能也会容易得多,您基本上只需要尽早在某个地方拦截您的请求,以根据 URL 决定租户并指向正确的数据库。每个租户也可以轻松进行备份,如果您打算允许他们下载备份,则特别有用。
另一方面,也有理由不这样做。您将需要处理大量数据库模式,并且必须独立更新它们(如果您想避免因模式更改而导致所有租户停机,这实际上可能是一个优势,您可以逐步推出它们)。它允许您在特殊情况下将平台视为一次性升级的真正多租户 SaaS 部署,从而在生产中管理多个版本。最后,我听说几乎每个数据库供应商在一次安装中支持的模式实例数量都存在一个突破点(据推测有些可能会达到数十万个)。
当然,这实际上取决于您的用例。您提到了单一租户,这让我相信您现在没有太多租户,但您确实提到了要增加很多租户。我不确定你的意思是数百还是数百万,但无论哪种方式,我希望这对你的考虑有所帮助。祝你好运!
All of the technologies that you listed are quite common and reasonable for both single- and multi-tenant applications. I'd say supporting the 7 "things" for SaaS is much more of a function of how you use the technologies than which. It sounds like you already have a single-tenant application that works. So there's probably not much reason to deviate from the technology selections there unless something is just not working very well already. Your question is otherwise fairly open-ended though, so it's hard to be too much more specific there.
I do have some feedback on splitting the database (and perhaps other things) by tenant ID though. If you know you might eventually have a lot of tenants (say many thousands or more, particularly if they're small) then what you suggest is perhaps best. If however you'll have a smaller number of tenants (particularly if they're large) you might want to consider a database per tenant, so they each have their own table space. By that I mean a single database installation with multiple instances of the same schema inside of it, one per tenant.
There are a few reasons this can be an advantage. One is performance as you mentioned. Adding a tenant ID to every single table is overhead on disk access, query time and increases code complexity. Every index in the database will need to include the tenant ID as well. You run an additional risk of mixing data between tenants if you're not careful (although a Hibernate filter would help mitigate that). With a database per tenant you could restrict access to only the correct one. Porting your current application will probably be a lot easier too, you basically just need to intercept your request somewhere early to decide the tenant based on the URL and point to the right database. Backups are also easy to do per tenant, particularly useful if you ever intend on allowing them to download a backup.
On the other hand there are reasons not to do this. You'll have a lot of database schemas to deal with and they'll have to be updated independently (which can actually be an advantage if you want to avoid taking all tenants down for a schema change, you can roll them out incrementally). It lets you have special cases that could deviate from treating the platform as a true multi-tenant SaaS deployment that's upgraded all at once, resulting in management of multiple versions in production. Lastly I've heard there is a breaking point with just about every database vendor out there in the number of schema instances they'll support in one installation (supposedly some can go to hundreds of thousands though).
It really depends on your use case of course. You mentioned single-tenant which leads me to believe you don't have too many tenants right now, however you do mention growing to lots of tenants. I'm not sure if you mean hundreds or millions, yet either way I hope this helps some with your considerations. Best of luck!
没有简单的答案。我可以描述我自己的解决方案。它可以作为其他人的灵感。
详细信息请参见:
There is no simple answer. I can describe my own solution. It may serve as an inspiration for the others.
Details here: http://blog.trixi.cz/2012/01/multitenancy-using-spring-and-postgresql/
对于 (1):Hibernate 从版本 4 开始支持开箱即用的多租户配置。
在撰写本文时,支持的是每个租户数据库和每个租户模式,并且尚不支持使用鉴别器将所有租户保留在同一数据库中。我们已在我们的应用程序中成功使用了此功能(每个客户端数据库方法)。
对于 (3):经过一番调查,我们决定与 Braintree 一起实施计费。许多人推荐的另一个解决方案:Authorize.net、Stripe、PayPal。
对于 (4):我们使用 Hibernate/Spring 和 JBoss Cache 的集群配置进行二级缓存。如今,这变得“普遍”,使用 Jelastic 等 PaaS 服务,您甚至可以开箱即用地对其进行预配置。
For (1): Hibernate supporting multi-tenant configurations out of the box from version 4.
At the moment of writing supported are DB-per-tenant and schema-per-tenant and keeping all tenants in a same DB using discriminator is not yet supported. We have used this functionality successfully in our application (DB-per-client approach).
For (3): After some investigation done we decided to go with Braintree to implement billing. Another solutions many people recommend: Authorize.net, Stripe, PayPal.
For (4): We have used clustered configuration with Hibernate/Spring and JBoss Cache for 2nd level caching. At these days this became "common" and using PaaS services like Jelastic you can even get it pre-configured out of the box.
您所描述的是一个为多个租户提供全方位服务的 Saas 风格应用程序。您必须决定一些事情,例如数据隔离有多重要?如果您正在为医疗或金融领域进行构建,数据隔离是一个关键因素。
好吧,我无法回答您的所有观点,但我建议您为您的应用程序查看每个租户数据库的方法,因为它提供了最高级别的数据隔离。
由于您正在使用 Java、Spring、Hibernate 堆栈,因此我可以通过我编写的一个小示例应用程序来帮助您。这是一个可以在本地笔记本电脑上快速运行的工作示例。我已在此处分享了它。请看一下,如果它回答了您的一些问题,请告诉我。
What you describe is a full service Saas style application serving multiple tenants. There are a few things you have to decide like how critical is data isolation? If you are building for a medical or financial domain, data isolation is a critical factor.
Well, I cannot help answer all your points, but I would suggest looking at database-per-tenant approach for your application as it provides the highest level of data isolation.
Since you are using the Java, Spring, Hibernate stack, I can help you with a small example application I wrote. It is a working example which you can quickly run in your local laptop. I have shared it here. Do take a look and let me know if it answers some of your questions.