Создание одного приложения с несколькими базами данных

Я не думаю, что правильно описал проблему через заголовок. Однако у меня есть приложение .NET Core Web Api, которое будут использовать все мои клиенты. Помимо одного экземпляра API у меня есть один внешний экземпляр Vuejs, который все арендаторы могут использовать в качестве «портала».

Каждый из этих арендаторов имеет свою собственную базу данных. В настоящее время всем API требуется заголовок tenant в запросе, чтобы указать, для какого арендатора делается запрос, после чего будет создано соединение с базой данных в соответствии с арендатором из запроса.

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

Я предполагаю, что то, на чем я застрял, - это определение арендатора, к которому принадлежит пользователь, при входе в систему с использованием единственного экземпляра внешнего интерфейса vuejs. Это не проблема, когда дело доходит до использования API, поскольку арендатор может быть отправлен через заголовок запроса, но я не уверен, как разрешить арендатора, чтобы определить правильную БД для использования по знаку, в котором будет используется всеми арендаторами.

Извините, если я не объяснил проблему хорошо, это сложная ситуация.

Если у каждого арендатора своя база данных, что мешает двум арендаторам иметь пользователей с именем name? Либо пользователь должен указать идентификатор арендатора в процессе входа в систему, либо вы должны хранить всех пользователей в общей базе данных.

John Wu 06.07.2019 01:18

@JohnWu Правда, арендатор может быть уникальным идентификатором. Однако, исходя из вашего второго предложения о хранении всех пользователей в общей базе данных, как это будет работать, если пользователь из общей базы данных должен использоваться для фактической базы данных арендатора.

KTOV 06.07.2019 01:21

Самый простой способ — объединить всю информацию об арендаторах в этой общей базе данных. Вот что значит мультиарендность. Если им необходимо иметь отдельные базы данных, вам потребуется двойная регистрация с копией списка пользователей каждого арендатора в его базе данных, специфичной для арендатора, что-то вроде того, как «логины» SQL Server сопоставляются с одним или несколькими «пользователями» базы данных.

John Wu 06.07.2019 01:23

Являются ли общие базы данных арендаторами хорошей идеей? @ДжонВу

KTOV 06.07.2019 01:26

Да! Сама идея мультитенантности заключается в объединении данных. Если вы беспокоитесь о производительности, вы масштабируете, например. добавьте больше процессоров и памяти или больше узлов в свой кластер БД. Это намного дешевле, чем поддержка индивидуальных баз данных для каждого нового клиента, и вам будет намного проще расти вместе с вашим бизнесом.

John Wu 06.07.2019 01:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
344
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Если бы все БД имели одинаковую структуру, я бы использовал только одну базу данных и использовал идентификатор арендатора в качестве индекса, таким образом, у вас есть только одно соединение в вашем проекте, и проблема решена. В противном случае вам придется проверять все базы данных каждый раз, когда пользователь пытается войти в систему.

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

trailmax 06.07.2019 00:44
Ответ принят как подходящий

где живут ваши пользователи? Возможно, вам придется извлечь информацию о пользователях в отдельную базу данных удостоверений, содержащую информацию о том, какой пользователь принадлежит какому арендатору. Это может быть так же просто, как хранилище ключей и значений: электронная почта->TenantId. Поэтому для входа в систему вам нужно будет найти это tenantId, а затем пройти аутентификацию по информации о пользователе в правильной базе данных арендатора.

Или вы можете собрать всю информацию о пользователе в единую базу данных, содержащую всю информацию о пользователе, включая хэш пароля. Вы также можете использовать какого-либо поставщика удостоверений, такого как Auth0 или IdentityServer — у них есть возможность добавлять пользовательские свойства, такие как TenantId.

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

Если ваше приложение Vue.js использует ваш серверный API, вы можете установить TenantId в файле cookie или другим способом, чтобы сохранять эту информацию между вызовами.

Я думал об этом, но ваша комбинация электронной почты и пароля может быть одинаковой для более чем 1 арендатора (в каком-то диком сценарии), что тогда делать?

KTOV 06.07.2019 00:48

Если у вас есть пользователи, использующие несколько арендаторов, вам придется выполнить сопоставление «один ко многим» от пользователя к арендаторам. И когда пользователь с несколькими арендаторами входит в систему, перенаправляйте их на страницу, где они выбирают, к какому арендатору они хотели бы перейти прямо сейчас.

trailmax 06.07.2019 03:36

Мне нравится эта идея, я решил создать для этого сервер идентификации, который будет хранить и обрабатывать аутентификации пользователей, но с моим приложением, использующим собственную базу данных, как будет выполняться ссылка на пользователя? Поскольку некоторые вещи, которые хранятся в базе данных арендатора, требуют хранения для пользователя

KTOV 06.07.2019 21:44

Обычно электронная почта работает как ключ между приложениями для получения информации о пользователе на сервере идентификации и в приложении. Но Guid также будет хорошим выбором. И прежде чем реализовать свой собственный, вы видели IdentityServer.io?

trailmax 06.07.2019 23:45

Да, спасибо за рекомендацию. На самом деле я только начал изучать Identity Server. Мой вопрос: могу ли я использовать Identity Server и .NET Identity Core для одновременного управления пользователями?

KTOV 07.07.2019 22:04

То есть я не знаю, я только немного поигрался с IdentityServer. Я думаю, что будет API, который вы сможете использовать в своем приложении.

trailmax 08.07.2019 14:54

Я бы использовал подобное решение, подобное этому

https://docs.servicestack.net/мультитенантность

ServiceStack provides a number of ways of changing the database connection used at runtime based on an incoming Request. You can use a Request Filter, use the [ConnectionInfo] Request Filter Attribute, use the [NamedConnection] attribute on Auto Query Services, access named connections in Custom Service implementations or override GetDbConnection(IRequest) in your AppHost.

Используете ли вы WebAPI или ServiceStack, решать вам (лично я являюсь поклонником последнего). По сути, вам нужно создать интерфейс IForTenant и реализовать его в своих сервисных моделях.

public interface IForTenant
{
    string TenantId { get; }
}

Вам понадобится фабрика соединений с БД, которая принимает идентификатор арендатора в качестве аргумента для возврата экземпляра IDbConnection. Затем вы создаете фильтр запросов, который проверяет, относится ли запрос к типу IForTenant, и получает правильный экземпляр IDbConnection из вышеупомянутой фабрики.

Я думаю, что каждая служба, реализующая IForTenant, немного излишняя, не так ли? Действительно, соединение с БД может быть определено до того, как контроллер обработает запрос.

KTOV 06.07.2019 01:17

Вы также можете проверить заголовки запросов на наличие определенного ключа внутри ваших фильтров запросов (вы даже можете создать метод расширения для более четкого дизайна). Затем вы вводите свой IDbConnectionFactory в свои контроллеры и вызываете GetConnection(tenantId), чтобы получить соответствующее соединение. Как вы думаете?

Eyassu 06.07.2019 01:28

Другие вопросы по теме