Добрый день!
В компании есть несколько отдельных систем, например, "Система управления персоналом" (Кадры), "Система службы поддержки" (Поддержка) и "Система заключения договоров" (Договоры).
В системе Договоры и Поддержка требуются данные о сотрудниках из системы Кадры, а в системе Поддержка требуются данные по договорам обратившихся пользователей. И так далее, в реальности количество систем > 5 и
они должны быть связаны друг с другом. Все системы являются web-системами и разработаны на ASP.NET MVC.
Вопрос каким способом лучше обеспечить взаимодействие между системами?
Я рассматриваю следующие способы:
I. Сервисные библиотеки
Такой подход используется на данный момент.
Для каждой системы-поставщика написаны отдельные .NET библиотеки-сервисы).
Например, для системы Кадры создан модуль, интерфейс и реализация которого, в упрощенном виде (убрать ORM, другие зависимости и прочее), может выглядеть так:
public interface IStaffService
{
EmployeeDto GetEmployee(int id);
IEnumerable<EmployeeDto> GetEmployees(EmployeeQuery query);
}
public class StaffService
{
private string _connectionString { get; }
public StaffService(string connectionString)
{
Ensure.NotEmpty(connectionString, nameof(connectionString));
_connectionString = connectionString;
}
public EmployeeDto GetEmployee(int id)
{
// use _connectionString ...
}
public IEnumerable<EmployeeDto> GetEmployees(EmployeeQuery query)
{
//use _connectionString ...
}
}
Эти библиотеки размещены в корпоративном NuGet и устанавливаются в требуемых приложениях. Например, указанный IStaffService будет установлен через NuGet в проект с системой Договор и будет вызываться. В целом всё это сделано для того, чтобы в каждой системе не писать такой сервис (одинаковый везде). Получается своеобразный вариант API только на backend.
Основные плюсы и минусы такого подхода:
Плюсы:
- Скорость работы. Работа ведётся точно также, если бы эти методы писали в самой системе;
- Простота эмуляции для тестов.
Минусы:
- Очевидно клиентская система использующая такой сервис должна иметь доступ к БД, так как нужно указывать ConnectionString;
- Возможно дублирование бизнес логики - один раз в используемой системе, второй раз в её модуль-сервисе;
- При исправлении логики работы какого-то метода необходимо обновить NuGet-пакет во всех системах, которые его используют и заново развернуть эти системы на prod.
Сейчас это текущее решение подвергается сильным сомнениям в его дальнейшем использовании из-за описанных минусов.
II. REST API
API в каждой системе. И соответственно потребительские системы дёргают методы этого API для получения данных.
Основные плюсы и минусы такого подхода:
Плюсы:
- Полное инкапсулирование бизнес логики. Всё, что касается системы, написано только в ней. Никаких сторонних библиотек для этого делать не нужно;
- В отличие от предыдущего способа, в случае исправления логики работы какого-то метода API обновлять что-то в другим системах не нужно. Они как использовали метод API так и используют, только теперь получает правильные данные.
Минусы:
- Скорость работы. Сетевые расходы. Обмен данными происходит по сети в формате json;
- В той реализации, в которой я себе это сейчас представляю для того чтобы связать система Договоры начала потреблять API системы Кадры - нужно не только в системе договоры прописать endpoint, client_id и client_secret, но в Кадры внести схожую информацию. Получается, что если появляется новый потребитель, приходится вносить изменения еще и в систему-поставщик (в её конфигурацию).
III. Корпоративная сервисная шина данных (ESB).
Взять MassTransit/NServiceBus/EasyNetQ и RabbitMQ/Kafka и реализовать обмен сообщениями между системами.
Но честно говоря вся эта история с очередями кажется слишком громоздкой для текущих условий.
Вопрос заключается в следующем:
Коллеги, просьба поделиться мыслями или best practices - Как связать N систем (при условии, что системы не очень большие), какой подход лучше использовать? Возможно вообще стоит делать как-то по другому?
Спасибо за помощь и советы!