Немного фона
Я использую жемчужину квартиры для запуска многопользовательского приложения в течение многих лет. В последнее время возникла необходимость масштабирования базы данных на отдельные хосты, сервер БД просто не может больше поддерживать (и при чтении, и при записи получается слишком много) - и да, я масштабировал оборудование до максимума (выделенный аппаратное обеспечение, 64 ядра, 12 дисков Nvm-e в raid 10, оперативная память 384 ГБ и т. д.).
Я подумывал сделать это для каждого арендатора (1 клиент = 1 конфигурация / пул соединения с базой данных), так как это был бы «простой» и эффективный способ получить в number-of-tenants
разы большую емкость без внесения изменений в код приложения.
Сейчас я бегу по рельсам 4.2 атм., Скоро обновляюсь до 5.2. Я вижу, что в rails 6 добавлена поддержка определений соединений для каждой модели, однако это не совсем то, что мне нужно, поскольку у меня есть полностью зеркальная схема базы данных для каждого из моих 20 арендаторов. Обычно я переключаю «базу данных» по запросу (в промежуточном программном обеспечении) или по фоновому заданию (sidekiq middleware), однако в настоящее время это тривиально и обрабатывается в самоцвете «Квартира», поскольку оно просто устанавливает search_path
в Postgresql и фактически не меняет фактическое соединение. При переходе на индивидуальную стратегию хостинга мне нужно будет переключать все соединение для каждого запроса.
Вопросов:
- Я понимаю, что мог бы выполнять работу
ActiveRecord::Base.establish_connection(config)
по запросу / фону - однако, как я понимаю, это инициирует совершенно новое установление соединения с базой данных и создание нового пула базы данных в рельсах - правильно? Я полагаю, что это было бы самоубийством из-за производительности, чтобы сделать такие накладные расходы на каждый запрос к моему приложению. - Поэтому мне интересно, может ли кто-нибудь увидеть вариант с рельсами, например, предварительно установить несколько (всего 20) соединений / пулов базы данных с самого начала (например, при загрузке приложения), а затем просто переключаться между этими пулами для запроса? Так что он дБ подключений уже сделан и готов к использованию.
- Является ли все это просто плохой плохой идеей, и я должен вместо этого искать другой подход? Например, 1 экземпляр приложения = одно конкретное соединение с одним конкретным арендатором. Или что-то другое.
источник
master
ветку Rails . Будет ли запуск Rails Egde вариантом или обратным выводом этой функции в вашу текущую версию Rails?ActiveRecord::Base.connected_to(shard: :shard_one) do ... end
означает, что пул будет (повторно) использоваться вместо создания нового соединения каждый раз?Ответы:
Как я понимаю, для мультитенантного приложения существует 4 шаблона:
1. Выделенная модель / несколько производственных сред
Каждый экземпляр или экземпляр базы данных полностью содержат различные приложения-арендаторы, и между ними ничего не распределяется.
Это 1 экземпляр приложения и 1 база данных для 1 арендатора. Разработка будет простой, как если бы вы обслуживали только одного арендатора. Но для девопов будет кошмар, если у вас, скажем, 100 арендаторов.
2. Физическая сегрегация арендаторов
1 экземпляр приложения для всех арендаторов, но 1 база данных для 1 арендатора. Это то, что вы ищете. Вы можете использовать
ActiveRecord::Base.establish_connection(config)
, или использовать драгоценные камни, или обновить до Rails 6, как предлагают другие. Смотрите ответ для (2) ниже.3. Модель изолированной схемы / Логические сегрегации
В изолированной схеме таблицы арендаторов или компоненты базы данных объединяются в логическую схему или пространство имен и отделяются от других схем арендаторов, однако схема размещается в том же экземпляре базы данных.
1 экземпляр приложения и 1 база данных для всех арендаторов, как вы делаете с квартирой драгоценный камень.
4. Частично изолированный компонент
В этой модели компоненты, имеющие общие функции, совместно используются арендаторами, в то время как компоненты с уникальными или несвязанными функциями изолированы. На уровне данных общие данные, такие как данные, идентифицирующие арендаторов, группируются или хранятся в одной таблице, в то время как данные, специфичные для арендаторов, изолируются на уровне таблицы или экземпляра.
Что касается (1),
ActiveRecord::Base.establish_connection(config)
не рукопожатие в дБ за запрос, если вы используете его правильно. Вы можете проверить здесь и прочитать все комментарии здесь .Что касается (2), если вы не хотите использовать
establish_connection
, вы можете использовать gem multiverse (это работает для rails 4.2) или другие драгоценные камни. Или, как другие предлагают, вы можете обновить до Rails 6.Редактировать: Multiverse Gem используется
establish_connection
. Он добавитdatabase.yml
и создаст базовый класс так, чтобы каждый подкласс разделял одно и то же соединение / пул. В основном это уменьшает наши усилия по использованиюestablish_connection
.Что касается (3), ответ:
Если у вас не так много арендаторов, а ваше приложение довольно сложное, я предлагаю вам использовать шаблон Dedicated Model. Таким образом, вы выбираете 1 экземпляр приложения = одно конкретное соединение с одним конкретным арендатором. Вам не нужно делать приложения более сложными, добавляя несколько соединений с базой данных.
Но если у вас много арендаторов, я предлагаю вам использовать Физическое разделение арендаторов или Частично изолированный компонент в зависимости от вашего бизнес-процесса.
В любом случае, вы должны обновить / переписать ваше приложение, чтобы соответствовать новой архитектуре.
источник
establish_connection
в модели, подобной этой:class SecondTenantUser < ActiveRecord::Base; establish_connection(DB_SECOND_TENANT); end
и скажете, что у вас 5 моделей, вы создаете 5 пулов соединений с DB_SECOND_TENANT. И к каждому пулу относятся одинаково. Таким образом, вы создаете пул не по запросу, а по запросуestablish_connection
.Из того, что я понимаю, (2) должно быть возможно с ручным переключением соединения в Rails 6.
источник
Буквально пару дней назад горизонтальный шардинг был добавлен в
master
ветку Ruby on Rails на GitHub. В настоящее время эта функция официально не выпущена, но в зависимости от версии Rails вашего приложения вы можете рассмотреть возможность использования Railsmaster
, добавив это вGemfile
:С помощью этой новой функции вы можете использовать пул соединений с базой данных Rails и переключать базу данных в зависимости от условий.
Я не использовал эту новую функцию, но она кажется довольно простой:
Вы не добавили подробных сведений о том, как вы определяете номер арендатора или как выполняется авторизация в вашем приложении. Но я постараюсь определить номер арендатора как можно скорее
application_controller
вaround_action
. Примерно так может быть отправной точкой:источник
ActiveRecord::Base.connected_to ... do
блока, он снова будет использовать соединение по умолчанию.master
ветку Rails .