Несколько эластичных пулов Azure SQL (Multi-Tenant SaaS)
Предположим, я хочу создать мультитенантное приложение SaaS с использованием ASP.NET Core и использовать эластичный пул Azure SQL, как в этом примере: Microsoft Docs
Максимальное количество баз данных в пуле - 500: цены Azure.
Дополнительная информация:
Я начну с единой базы данных Azure SQL
Я буду использовать Entity Framework Core
Вопросы:
Что произойдет, если мое приложение превышает 500 пользователей? Какие есть варианты для эффективного масштабирования? (когда вы достигнете предела эластичного пула)
Насколько хорошо этот вариант подходит для миграции EF Core?
Есть ли другие предложения о том, как начать и подойти к этому позже?
1 ответ
Контекст ответа
Прежде чем отвечать на ваши конкретные вопросы, позвольте мне добавить некоторый контекст о решении, которое я вижу. С мультиарендностью приходит управление арендаторами. И, как и в документе, на который вы ссылаетесь, вероятно, будет какой-то каталог, содержащий всю информацию, относящуюся к клиенту. Одна из этих частей информации может (скорее всего, будет) быть строкой подключения к базе данных конкретного клиента.
Представьте, что клиент подключается, и система получает базу данных для подключения из каталога в зависимости от того, какой это клиент (назовем это контекстом клиента). Приложение передаст строку подключения остальной части приложения для работы.
И вот в чем прелесть решения: эта строка подключения может указывать (практически) куда угодно. Он может указывать на базу данных в пуле или на управляемый экземпляр. Он может даже указывать на локальную базу данных, доступную через Интернет. Все потому, что приложение не зависит от того, где находятся данные, оно просто получает строку подключения и приступает к работе.
1. Что произойдет, если мое приложение превышает 500 пользователей? Какие есть варианты для эффективного масштабирования? (когда вы достигнете предела эластичного пула)
Если под пользователями вы имеете в виду арендаторов: ничего не происходит. Новые базы данных создаются в любом месте, доступном для приложения, например, в новом пуле. И поскольку строка подключения для клиента может указывать куда угодно, это совершенно нормально.
2. Насколько хорошо этот вариант подходит для миграции EF Core?
Этот вариант подходит как для миграции EF Core, так и для любой другой модели базы данных: обновления базы данных должны выполняться надлежащим и управляемым образом. Это можно сделать, например, запустив миграцию или сценарий обновления. Факт остается фактом: вам нужно обновить несколько баз. И для того, чтобы это сработало, разумно иметь приличный план миграции.
Есть несколько способов смягчить возможные проблемы или, по крайней мере, ограничить возможность поломки. Можно было бы создавать только миграции, которые только добавляют к вашей текущей модели. Другой вариант - отделить модель базы данных от приложения за счет наличия асинхронного коммуникационного уровня между ними, например служебной шины.
Это довольно сложная для определения стратегия, которая во многом зависит от таких факторов, как тип создаваемого вами приложения, частота, с которой у вас будут обновления базы данных, и сложность схемы вашей базы данных.
3. Есть ли другие предложения о том, как начать и как подойти к этому позже?
Насколько я понимаю: если вы знаете, что это произойдет, действуйте сейчас. Проще всего реализовать мультиарендность на ранней стадии. Чем дальше по дороге, тем сложнее, потому что вы, вероятно, начнете жестко кодировать (не совсем, а вроде как) соединения в своем приложении, которые нужно отделить, как только вы захотите добавить мультитенантность.
Вывод
Если я правильно истолковал ваш вопрос, вы знаете, что мультитенантность станет "вещью" для вашего приложения. Это означает, что вам нужно заняться этим с самого начала. Но вам не обязательно иметь полноценную мультитенантность с самого начала... вам просто нужно к этому подготовиться.
Немного технически: вы могли бы, например, реализовать TenantContext
который идентифицирует клиента при входе в систему и получает сопутствующие строки подключения (хранилище, служебная шина, база данных и т. д.) при входе в систему. Затем в остальной части приложения получите строки подключения изTenantContext
и использовать их для получения данных для конкретного клиента.
Сначала, например, во время разработки, контекст может быть очень простым и возвращать информацию только для одного арендатора. Но из-за введенной вами развязки остальная часть приложения уже подготовлена для мультитенантности. Как только потребность в этом станет реальной, все, что вам нужно сделать, это реализоватьTenantContext
.
EDIT:
В
качестве дополнения из - за комментарий ниже: есть это способ регистраDbContext
экземпляры в системе DI заранее. Вы можете реализовать что-то вродеConnectionStringResolver
который вводится в контекст. Как только вам действительно понадобится DbContext, станет известен и контекст клиента. DbContext создается с использованиемConnectionStringResolver
чтобы найти правильную строку подключения для клиента.