編寫一個多租戶Rails 3應用程序,以便在Heroku上進行部署

[英]Writing a multi-tenant Rails 3 app for deployment on Heroku


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.

我正在構建一個用於在Heroku上部署的Rails 3應用程序,我想知道是否有關於如何在我的模型中處理多租戶的任何建議。半年前,有一個相關問題(#3776593)發布在這里,但沒有得到很多答案。我還看過Guy Naor關於使用Rails編寫多租戶應用程序的演講,但似乎3個提議的解決方案中有2個不適用於Heroku。我將鏈接到這些,但新的Stackoverflow用戶限於2個超鏈接。

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!

只是想知道你是否有使用多租戶寶石或簡單軌道多租戶寶石的經驗。似乎最簡單的解決方案是簡單地將belongs_to放在我需要在賬戶下的所有模型上,但我真的很想知道你在現實世界中使用了什么!

3 个解决方案

#1


6  

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.

所有這些都在某種程度上是平台特定的。當dbms禁止查詢訪問多個數據庫時,“每個租戶一個數據庫”具有最高的隔離度。但是某些平台允許跨多個數據庫進行查詢。

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

MSDN有一篇不錯的文章可以達到最高點:多租戶數據架構。

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.

但如果你只限於Heroku,你必須選擇Heroku支持的選項。我不知道這些選項可能是什么,但我知道你最好不要在開發中使用SQLite。 Heroku部署將在PostgreSQL上運行;你需要針對PostgreSQL進行開發。

#2


6  

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.

作為多租戶寶石的作者,我顯然有偏見,但我真的相信這是一個很好的解決方案! gem的目標是簡化這種常見的應用程序需求,並使其實現變得微不足道。

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.

“舊學校”替代方案是使用rails對象鏈接來確保所有查詢都通過關聯的父級完成。這種方法的問題在於您的租戶對象成為has_many關聯的傾倒場所。

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.

多租戶gem通過確保生成的所有查詢自動識別當前租戶來解決此問題。它還確保創建新記錄並自動分配給當前租戶,這樣您就不需要添加任何特殊的before_save回調。

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

#3


2  

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.

我即將開始這個冒險(實現小型鐵路應用程序的多租戶),在做研究時我偶然發現了這個SO帖子。

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

令人驚訝的是,沒有人提到RyanB使用Heroku支持的PostgreSQL模式實現MT的精彩截屏。

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

以下是截屏視頻的鏈接http://railscasts.com/episodes/389-multitenancy-with-postgresql。

Concept:

概念:

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

在rails app中,我們可以為pg連接設置搜索路徑

      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.

如果在schema1找到相應的表,則將在schema1上執行任何后續操作。否則,它會搜索schema2中的表,依此類推。與您的整個應用程序架構(包括租戶)一起使用將是公開的,通常的做法是在公共架構中使除租戶之外的所有表都為空。

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.

將after_create函數添加到租戶模型以為新租戶創建新架構,並將所有(加載schema.rb)應用表(租戶除外)創建到此新架構中。

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.

當用戶訪問subdomain1.myapp.com時,從租戶表中查找此子域的架構,並將連接搜索路徑設置為“schema1,public”並對用戶進行身份驗證。

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

請注意,我的目的只是為了涵蓋解決方案背后的概念。有關實際解決方案,請參閱RyanB的截屏視頻。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2011/05/06/72f26ae934d2ee980a46e2357c6736e2.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com