编写多租户 Rails 3 应用程序以在 Heroku 上部署

发布于 2024-11-05 09:46:31 字数 990 浏览 4 评论 0原文

我正在构建一个用于在 Heroku 上部署的 Rails 3 应用程序,我想知道是否有关于如何在我的模型中处理多租户的建议。半年前,有一个相关的问题(#3776593)发布在这里,但没有得到很多答案。我还观看了 Guy Naor 关于使用 Rails 编写多租户应用程序的演示,但似乎 3 个提议的解决方案中的 2 个不适用于 Heroku。我会链接到这些,但新的 Stackoverflow 用户仅限于 2 个超链接。

我还遇到过以下工具:

只是想知道您是否有这方面的经验多租户 gem 或 simple-rails-多租户 gem。似乎最简单的解决方案是简单地在需要在帐户下的所有模型上放置一个belongs_to,但我真的很想知道您在现实世界中使用什么!

I'm building a Rails 3 app for deployment on Heroku, and I'm wondering if there are any recommendations on how to handle multi-tenancy in my models. Half a year ago, there was a related question (#3776593) posted on here, but it didn't get many answers. I've also watched Guy Naor's presentation on writing multi-tenant applications with Rails, but it seems like 2 of the 3 proposed solutions wouldn't work on Heroku. I'd link to these, but new Stackoverflow users are limited to 2 hyperlinks.

I've also come across the following tools:

Just wondering if you have experience with either the multitenant gem or the simple-rails-multi-tenancy gem. Seems like the most straightforward solution would be to simply put a belongs_to on all my models that need to be under an Account, but I'd really like to know what you're using in the real world!

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

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

发布评论

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

评论(3

猫九 2024-11-12 09:46:31

这些方法的范围从“不共享任何内容”(这通常意味着每个租户一个数据库)到“共享所有内容”(这通常意味着每个表包含来自许多租户的行)。该范围(如下)可以按隔离程度、成本(即每个租户的成本)以及灾难恢复的难易程度进行细分。

  • 每个租户一个数据库;成本最高、隔离程度最高、恢复最容易。
  • 每个租户一个模式;其他两者之间的成本,良好的隔离,相当容易的恢复,但恢复通常会降低其他租户的性能。
  • 租户之间共享餐桌;成本最低、隔离性最低(共享表)、灾难恢复困难(恢复通常意味着为每个表恢复一些行)。恢复通常会降低其他租户的性能“很多”。

所有这些在某种程度上都是特定于平台的。当 dbms 禁止查询访问多个数据库时,“每个租户一个数据库”具有最高的隔离性。但有些平台允许跨多个数据库查询。

MSDN 有一篇不错的文章,抓住了要点:多租户数据架构

但如果您仅限于 Heroku,则必须选择 Heroku 支持的选项。我不知道这些选项可能是什么,但我确实知道您最好不要在开发中使用 SQLite。 Heroku 部署将在 PostgreSQL 上运行;你需要针对 PostgreSQL 进行开发。

The approaches range from "share nothing", which usually means one database per tenant, to "share everything", which usually means each table contains rows from many tenants. The spectrum (below) can be broken down by degree of isolation, by cost (cost per tenant, that is), and by ease of disaster recovery.

  • One database per tenant; highest cost, highest isolation, easiest recovery.
  • One schema per tenant; cost between the other two, good isolation, fairly easy recovery, but recovery usually degrades performance for other tenants.
  • Share tables among tenants; lowest cost, lowest isolation (shared tables), difficult disaster recovery (recovery usually means recovering some rows for every table). Recovery usually degrades performance "a lot" for the other tenants.

All those are platform-specific to some degree. "One database per tenant" has the highest isolation when the dbms prohibits queries from accessing more than one database. But some platforms allow querying across multiple databases.

MSDN has a decent article that hits the high points: Multi-Tenant Data Architecture.

But if you're limited to Heroku, you'll have to pick an option that Heroku supports. I don't know what those options might be, but I do know that you're better off not using SQLite in development. Heroku deployments are going to run on PostgreSQL; you need to develop against PostgreSQL.

旧伤还要旧人安 2024-11-12 09:46:31

作为多租户 gem 的作者,我显然有偏见,但我真的相信这是一个很好的解决方案! gem 的目标是简化这种常见的应用程序需求并使其易于实现。

“老派”替代方案是使用 Rails 对象链来确保所有查询都是通过关联的父级完成的。这种方法的问题在于,您的 Tenant 对象会成为 has_many 关联的垃圾场。

class Tenant
  has_many :users
end
# query for users in the current tenant
current_tenant.users.find params[:id]

多租户 gem 通过确保生成的所有查询自动了解当前租户来解决这个问题。 它还确保创建新记录并自动分配给当前租户,因此您无需添加任何特殊的 before_save 回调。

前任:

Multitenant.with_tenant current_tenant do
  # queries within this block are automatically
  # scoped to the current tenant
  User.all

  # records created within this block are
  # automatically assigned to the current tenant
  User.create :name => 'Bob'
end

As the author of the multitenant gem, I'm obviously biased, but I really believe that it is a great solution! The goal of the gem is to simplify this common application need and make it trivial to implement.

The "old school" alternative is to use rails object chaining to ensure that all queries are done through the associated parent. The issue with this approach is that your Tenant object becomes a dumping ground for has_many associations.

class Tenant
  has_many :users
end
# query for users in the current tenant
current_tenant.users.find params[:id]

The multitenant gem solves this by ensuring that all queries generated are automatically aware of the current tenant. And it also ensures that new records are created and automatically assigned to the current tenant so you don't need to add any special before_save callbacks.

ex:

Multitenant.with_tenant current_tenant do
  # queries within this block are automatically
  # scoped to the current tenant
  User.all

  # records created within this block are
  # automatically assigned to the current tenant
  User.create :name => 'Bob'
end
自在安然 2024-11-12 09:46:31

我即将开始这项事业(为小型 Rails 应用程序实现多租户),在进行研究时我偶然发现了这篇 SO 帖子。

令人惊讶的是,没有人提到 RyanB 关于使用 Heroku 支持的 PostgreSQL 模式实现 MT 的精彩截屏视频。

以下是截屏视频的链接 http://railscasts.com/episodes/389-multitenancy- with-postgresql

概念:

在rails应用程序中,我们可以为pg连接设置搜索路径,

      connection.schema_search_path = "schema1, schema2, ..."

如果在schema1上找到相应的表,则后续操作将在schema1上执行。否则,它会搜索 schema2 中的表,依此类推。为了与包括租户在内的整个应用程序模式一起使用,通常的做法是在公共模式中将除租户之外的所有表设为空。

新租户注册:

向租户模型添加 after_create 函数,为新租户创建新架构,并将所有(加载 schema.rb)应用程序表(租户除外)创建到此新架构中。

用户:

当用户访问 subdomain1.myapp.com 时,从租户表中查找该子域的架构,并将连接搜索路径设置为“schema1,public”并对用户进行身份验证。

请注意,我的目的只是介绍解决方案背后的概念。有关实际解决方案,请参阅 RyanB 的截屏视频。

I am about to embark on this venture(implementing multi-tenancy for a small rails app) and while doing research I stumbled on this SO post.

It is surprising that no one mentioned about the great screencast by RyanB on implementing MT using PostgreSQL schemas which is supported by Heroku.

Here is the link to the screencast http://railscasts.com/episodes/389-multitenancy-with-postgresql.

Concept:

In rails app,we can set a search path for pg connection

      connection.schema_search_path = "schema1, schema2, ..."

any subsequent actions will be executed on schema1 if it finds the corresponding table there. Otherwise, it searches for the table in schema2 and so on. To being with your entire app schema including tenant will be in public and usual practice is to make all the tables except tenant empty in public schema.

New Tenant Registration:

Add an after_create function to your Tenant model to create a new schema for the new tenant and create all (load schema.rb) app tables (except Tenant) into this new schema.

User:

when a user visits, subdomain1.myapp.com, find the schema for this subdomain from tenant table and set the connection search path to 'schema1, public' and authenticate the user.

Please note, my intention is just to cover the concept behind the solution. Refer to RyanB's screencast for the actual solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文