Мультитенантность (мультиарендность) – особенность архитектуры ПО, которая позволяет приложению обслуживать несколько независимых арендаторов. Пользователи не мешают друг другу, их данные хранятся независимо и безопасно, а разработчики могут быстро запускать версии продукта с разными техническими возможностями.
В первую очередь мультитенантность нужна SaaS-продуктам, но не только. Этот подход применяется везде, где компания параллельно поддерживает несколько версий одного продукта.
![](https://habrastorage.org/getpro/habr/upload_files/89e/d79/5b6/89ed795b6b0e276c89f58219afa49436.png)
Например:
Одно подразделение в компании продаёт услуги частным клиентам, другое работает с юридическими лицами. В обоих случаях сотрудники используют одну и ту же систему продаж, но набор функций им нужен разный.
Организация покупает стороннюю компанию, и её нужно подключить к приложению, с которым работают все сотрудники предприятия. При этом данные двух структур должны обрабатываться независимо, должны существовать независимые пространства имён.
Компания создаёт разные версии одного продукта, которые рассчитаны на разные группы пользователей. Ядро решения остаётся одним, а возможности меняются в зависимости от того, что нужно клиентам.
Без мультитенантности разработчикам приходится встраивать в код переключатели и ограничители функций, настраивать политики доступа, следить за тем, чтобы данные не пересекались, вручную управлять доступом к ресурсам. При запуске каждой новой фичи нужно тщательно продумать, кто должен с ней работать и как на архитектурном уровне ограничить доступ для тех, кому она не нужна.
В мультиарендном приложении функции можно включать и выключать для разных групп пользователей, на уровне поставок настраивать уровни доступа и правила обращения с данными. Даже если у продукта пять версий, управлять ими может одна команда разработчиков.
Мультиарендность обеспечивает бизнес-пользователям независимость процессов
Данные из каждого бизнес-модуля поступают в выделенную среду. Процессы внутри продукта организованы таким образом, чтобы разные арендаторы не мешали друг другу:
Микросервисная архитектура позволяет выделять ресурсы для разных процессов и распределять их между пользователями.
Службы метаданных и контекста получателя обрабатывают данные каждого отдельного бизнес-заказчика, позволяя каждому создавать собственные сущности для определения пользователей, систем-источников данных, и необходимых действий.
Ключи-идентификаторы используются для распределения потоков данных между разными пользователями и внутри своей собственной ИТ-экосистемы.
Всё это позволяет мультиарендному продукту разграничивать данные и процессы как на уровне отдельных заказчиков, так и на уровне конечных пользователей.
Возможные варианты архитектуры мультитенантных приложений
1. Единый пул ресурсов, единое хранилище данных, одна инсталляция, разделение на уровне софта.
Такое приложение само понимает, куда пустить каких пользователей и какие функции им требуются. Этот сценарий обеспечивает оптимальное использование ресурсов, простое администрирование и развитие ПО.
Это мультиарендность на уровне ядра. Именно по такому пути стоит следовать, если вы создаёте мультитенантное приложение с нуля.
2. Единое хранилище данных, одна инсталляция ПО, пул ресурсов у каждого тенанта свой.
В этом случае разделение между арендаторами происходит на уровне инфраструктуры. Каждая группа пользователей заходит на свой URL или подключается к собственному серверу.
В этом случае ресурсы используются менее экономично, зато у каждого арендатора есть гарантированные мощности – ведь он использует собственный пул. Архитектурно такой подход проще, чем первый вариант, и если у вашей компании есть собственный ЦОД, он действительно может оказаться оптимальным.
3. У каждого арендатора есть собственная инсталляция ПО, собственный пул ресурсов, собственное хранилище.
Наименее экономичный вариант, требует больше всего ресурсов поддержки. По сути своей, каждый арендатор получает собственную копию приложения. Так что и разработчикам нужно развивать каждую версию отдельно, и поддержка у них строится независимо. Если компании нужно контролировать всю ситуацию целиком, нужно строить некое интеграционное решение.
Такой сценарий подходит для приложений, которые разрабатывались без расчёта на мультиарендное использование. Это не мультитенантность в полном смысле этого слова – скорее, способ добиться части её возможностей, когда переделывать продукт оказывается слишком дорого или нецелесообразно по другим причинам.
Что нужно, чтобы сделать продукт мультитенантным
Мультитенантность закладывается на уровне архитектуры, так что в идеальной ситуации нужно продумывать такие возможности нужно с самых первых шагов работы над приложением.
Разработка мультитенантных продуктов строится по принципу Feature-driven Development (Trunk-based Development). Разработчики создают новые функции, которые можно включать и выключать для разных групп пользователей.
Именно с перехода на Trunk-based Development мы рекомендуем начинать путь к мультитенантности. Это позволит разработчикам взглянуть на продукт как на набор функций, из которых можно составлять параллельные версии.
PrinceKorwin
Спорное утверждение. Очень. Этот путь самый дешевый с точки зрения затрат на железо, но чревато тем, что это путь в вечные баги.
Т.к. изоляция данных на уровне бизнес-логики, то нужно везде-везде учитывать идентификатор тенанта чтобы ни дай боже не подтянуть или не засветить (а тем более не потереть) данные другого тенанта. И такие баги не очень то легко уловимы, а бед от них много, включая ухудшение имиджа компании, судебные издержки и возможные штрафные санкции.
А как делать backup данных для каждого тенанта? Стандартные средства уже не помогут — добро пожаловать писать велосипед (тратить деньги).
А как обеспечивать отказоустойчивость (падает всё для всех сразу)?
Странно, но не рассмотрен сценарий:
Динамический пул ресурсов — у тенантов часть ресурсов может быть общая, а часть — разной.
раздельное хранилище данных — отдельные БД. Полная изоляция данных, стандартные схемы backup'а.
одна инсталляция — разделение на уровне софта.
При этом инсталляция может быть тоже динамической. Когда для части тенантов делается отдельная инсталляция (либо полностью, либо части решения).
gecube
именно так и должно быть, в частности, если у тенантов разные требования к ПДн и, например, разное отношение к GDPR.
true_engineering Автор
согласны, мы неточно выразились в тексте — такой вариант отчасти подразумевается в п.2: "разделение между арендаторами происходит на уровне инфраструктуры. Каждая группа пользователей заходит на свой URL или подключается к собственному серверу".
что касается проблем с бизнес-логикой, то они сильно сокращаются, если мультитенантность приложения закладывается изначально, на уровне архитектуры. если на эти рельсы переводить уже работающий продукт, то, да, код придётся изрядно перерыть
PrinceKorwin
Они могут сокращаться только если используемый ORM позволяет сам автоматически править запрос так, чтобы вводить нужные ограничения по тенанту. Если же такой возможности нет и каждый разработчик должен помнить и руками выставлять такие ограничения — жди беды.
Поэтому мультитенантность на _общей_ базе данных — это заведомо ошибочный и дорогой путь.
Мультитенантность — она бывает разная. В частности в статье не озвучен вопрос кросс-мультитенантного взаимодействия. А такое бывает.
Или как сделать кастомизацию конкретного функционала под конкретного тенанта не дублируя при этом инстансы приложения (система плагинов с поддержкой мультитенантности). Это же касается и статических ресурсов (CSS, изображения, логотипы и т.д.).
А еще бывает так, что у каждого тенанта своя языковая локаль… В общем тема интересная, но раскрыта не полностью.