Написание многопользовательского Rails 3 приложения для развертывания на Heroku

Я создаю приложение Rails 3 для развертывания на Heroku, и мне интересно, есть ли какие-либо рекомендации относительно того, как обрабатывать многопользовательскую аренду в моих моделях. Полгода назад здесь был связан вопрос (# 3776593), но ответа у него не получилось. Я также смотрел презентация Guy Naor о написании многопользовательских приложений с Rails, но похоже, что 2 из 3 предлагаемых решений не будут работа на Хереку. Я бы связался с ними, но новые пользователи Stackoverflow ограничены двумя гиперссылками.

Я также сталкивался с следующими инструментами:

Просто интересно, есть ли у вас опыт работы с самоцветом мультитенциала или с камнем с простой решеткой. Похоже, что самым простым решением было бы просто поместить property_to на все мои модели, которые должны быть под учетной записью, но я бы очень хотел узнать, что вы используете в реальном мире!

Ответ 1

Подходы варьируются от "ничего общего", что обычно означает одну базу данных для каждого арендатора, чтобы "делиться всем", что обычно означает, что каждая таблица содержит строки от многих арендаторов. Спектр (ниже) можно разделить на степень изоляции, по стоимости (стоимость на одного арендатора, то есть), а также простоту аварийного восстановления.

  • Одна база данных для каждого арендатора; высокая стоимость, высокая изоляция, простое восстановление.
  • Одна схема для каждого арендатора; стоимость между двумя другими, хорошая изоляция, довольно легкое восстановление, но восстановление обычно ухудшает производительность для других арендаторов.
  • Обмен таблицами между арендаторами; низкая стоимость, самая низкая изоляция (общие таблицы), сложное аварийное восстановление (восстановление обычно означает восстановление некоторых строк для каждой таблицы). Восстановление обычно ухудшает производительность "много" для других арендаторов.

Все они в определенной степени зависят от платформы. "Одна база данных для каждого арендатора" имеет самую высокую степень изоляции, когда dbms запрещает запросы доступа к нескольким базам данных. Но некоторые платформы позволяют запрашивать несколько баз данных.

MSDN имеет достойную статью, которая поражает высокие точки: Архитектура данных с несколькими арендаторами.

Но если вы ограничены Героку, вам нужно выбрать вариант, который поддерживает Heroku. Я не знаю, какие могут быть эти параметры, но я знаю, что вам лучше не использовать SQLite в разработке. Развертывания Heroku будут запущены на PostgreSQL; вам нужно разработать против PostgreSQL.

Ответ 2

Как автор мультяшного драгоценного камня, я явно предвзято, но я действительно считаю, что это отличное решение! Цель драгоценного камня состоит в том, чтобы упростить эту общую потребность в приложении и сделать ее тривиальной для реализации.

Альтернативой "старой школы" является использование цепочки объектов rails для обеспечения того, чтобы все запросы выполнялись через связанный родитель. Проблема с этим подходом заключается в том, что ваш объект Tenant становится свалкой для ассоциаций has_many.

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

Мультенантский камень решает это, гарантируя, что все созданные запросы автоматически узнают о текущем арендаторе. И это также гарантирует, что новые записи создаются и автоматически назначаются текущему арендатору, поэтому вам не нужно добавлять специальные специальные обратные вызовы 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

Ответ 3

Я собираюсь начать это предприятие (внедряя многопользовательскую лицензию на небольшое приложение для рельсов), и, проводя исследования, я наткнулся на эту публикацию SO.

Удивительно, что никто не упомянул о большом скринкасте RyanB при реализации MT с использованием схем PostgreSQL, который поддерживается Heroku.

Вот ссылка на screencast http://railscasts.com/episodes/389-multitenancy-with-postgresql.

Концепция:

В приложении rails мы можем установить путь поиска для подключения pg

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

любые последующие действия будут выполняться на схеме1, если он найдет там соответствующую таблицу. В противном случае он ищет таблицу в схеме2 и т.д. Чтобы быть со всей схемой приложения, включая арендатора, будет публично, и обычная практика заключается в том, чтобы все таблицы, кроме арендатора, были пустыми в общедоступной схеме.

Регистрация нового арендатора:

Добавьте функцию after_create в вашу модель Арендатора, чтобы создать новую схему для нового арендатора и создать все (загрузите schema.rb) таблицы приложений (кроме Tenant) в эту новую схему.

Пользователь:

когда пользователь посещает subdomain1.myapp.com, найдите схему для этого поддомена из таблицы арендаторов и установите путь поиска соединения на "schema1, public" и аутентифицируйте пользователя.

Обратите внимание, что мое намерение состоит в том, чтобы охватить концепцию решения. Обратитесь к RyanB screencast за актуальным решением.