Мультитенантный микросервисный дизайн

13

Мы находимся в процессе миграции монолитного приложения на микросервисную архитектуру. Из-за некоторых нормативных требований мы должны хранить данные о клиентах из разных стран в отдельных (специфичных для страны) базах данных. То есть US db для клиентов в США, UK db для клиентов в Великобритании ...

Следующие проекты, которые мы рассматриваем, следующие:

Вариант 1: мультитенантное приложение с поддержкой мультитенантного режима гибернации, которое можно масштабировать до N раз в зависимости от спроса (вспомните о модулях kubernetes). Один экземпляр этого приложения сможет подключаться ко всем базам данных.

Вариант 2. Развертывание 1 экземпляра микросервиса для каждой базы данных страны. С шлюзом API перед ними маршрутизация трафика

Если бы вы разработали этот тип системы, каким был бы ваш выбор?

Привет мир
источник
3
Я думаю, что это будет зависеть от ваших конкретных функциональных и нефункциональных требований.
Роберт Харви
Разные базы данных, но один и тот же экземпляр читает? Разве это не нарушает нормативное требование?
Джимми Т.
Вариант 1 не слишком соответствует стилю архитектуры Microservices.
17
Вы упоминаете Kebernetes, но не ясно, используете ли вы контейнеры или нет. Если вы делаете это с помощью Docker (например), вы просто создадите приложение, которое подключается к базе данных. Затем при запуске контейнера и указании сведений о соединении через параметры и / или конфигурацию. Наличие одного приложения, которое подключается ко многим подобным базам данных, только создает потенциальные проблемы. Это не добавляет ничего хорошего к дизайну.
JimmyJames,

Ответы:

4

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

Важным фактором здесь является то, есть ли какая-либо разница между двумя схемами и будет ли когда-либо в будущем.

Обычно я думаю, что использование интерфейсов для репозиториев не нужно; однако, это может стоить усилий в этом случае. Хранилища заводов будут важны для вас.

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

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

public class MyEntityRepository : ISavesMyEntity, IGetsMyEntity
{
    public MyEntityRepository(string connectionString)
    {
       _connectionString = connectionString;
    }
}

public class MyEntitySaverFactory
{
    public ISavesMyEntity GetSaver(User user)
    {
        if (user.IsUK)
            return new MyEntityRepository(Config.Get("UKConnString"));
        if (user.IsUS)
            return new MyEntityRepository(Config.Get("USConnString"));
        throw new NotImplementedException();
    }
}

//USE
ISavesMyEntity saver = factory.GetSaver(currentUser);
saver.Save(myEntityInstance);

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

TheCatWhisperer
источник
1
Я не понимаю, зачем тебе эта фабрика. Почему бы просто не указать путь к деталям конфигурации при запуске? При этом вам нужно изменять код каждый раз, когда вы хотите добавить новый регион / страну.
JimmyJames
1
Проблема здесь не в том, чтобы иметь дело с пользователями в отдельных странах ... это в разных базах данных. Что делать, если есть разные схемы? Почему потребительский класс должен отвечать за выяснение, где взять строку подключения к БД?
TheCatWhisperer
Я не знаю, что ты имеешь в виду. Ничто в коде не должно отвечать за «выяснение», где взять строку подключения. Это конфигурация. Я не понимаю, почему это отличается от использования конфигурации для баз данных QA и производства. Вы не помещаете операторы if в код для этого?
JimmyJames
Это одно приложение, говорящее с двумя базами данных.
TheCatWhisperer
Я думаю, что вы неправильно понимаете проблему: «мы должны хранить данные клиента из разных стран в отдельных (специфичных для каждой страны) базах данных» Не требуется, чтобы один «экземпляр» приложения взаимодействовал с двумя базами данных. Я сомневаюсь, что это просто две БД. ОП, вероятно, означало «например», когда они
печатали
0

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

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

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

Есть смысл?

Шон Фармар
источник