@WhiteNinja

Как правильно интегрировать несколько систем в компании?

Добрый день!

В компании есть несколько отдельных систем, например, "Система управления персоналом" (Кадры), "Система службы поддержки" (Поддержка) и "Система заключения договоров" (Договоры).
В системе Договоры и Поддержка требуются данные о сотрудниках из системы Кадры, а в системе Поддержка требуются данные по договорам обратившихся пользователей. И так далее, в реальности количество систем > 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 систем (при условии, что системы не очень большие), какой подход лучше использовать? Возможно вообще стоит делать как-то по другому?

Спасибо за помощь и советы!
  • Вопрос задан
  • 231 просмотр
Решения вопроса 1
vabka
@vabka Куратор тега C#
Токсичный шарпист
Все варианты по своему допустимы и "правильного" пути тут нет.
1. Проблема может возникнуть, если БД системы изменится или понадобится какая-нибудь дополнительная валидация
2. Вроде ок, но нужно добавлять и поддерживать методы в каждой API-шке, и следить за совместимостью
3. Дополнительное звено в инфраструктуре. Придётся потратиться на развёртывание и поддержку, ну и заплатить задержками.

Я бы выбрал вариант с API тк он кажется самым адекватным в соотношении цена/качество.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
Jeer
@Jeer
уверенный пользователь
Привет,
Проблема существует практически на всех предприятиях, но обычно это разные системы, типа 1с на кадры, самописная c# по документам и какая-нибудь готовая опен-сорц система поддержки на php. Ваш вариант, что всё написано на одной технологии благо, используйте это, заворачивайте в нугет библиотеки.
Про esb - все очереди используются для синхронизации данных. То есть, у вас изменился некий сотрудник в кадрах, сохраняется не напрямую в бд, а через очередь. Другие системы так же подписаны на эту очередь и обновление сущности сотрудника идёт во всех системах, которые хранят дубли необходимых им данных. Как вы понимаете, тут куча накладных расходов и нештатных ситуаций. За этим нужно следить и как-то восстанавливать/докачивать данные. Тем не менее, это самый правильный вариант, ибо в противном случае синхронизацию данных делают кастылями через вьюхи/джобы/хранимки и как только отвратительно не делают. В общем, если хватает скиллов - делайте так, будут независимые рабочие приложения.
По общению через апи - там нет проблем с какими-то маленькими и атомарными операциями. Проблемы начинаются когда необходимы _распределённые транзакции_ погуглите про это, как реализовывают и оцените насколько тяжелее будет разработка. Вторая тут проблема - это отчёты, тупо джоины. Вам нужно выгрузить какую-то консолидированную инфу из одной системы, вы делаете, но в ней у вас только айдишники пользователей. Либо вы эти айдишники отправляете в сервис кадров и получаете развёрную инфу по каждому, либо на каждый такой запрос вообще грузите полный список пользователей. А потом ещё говорят, нужно исключить данные по пользователям на время их отсутствия. Опять же эти данные в сервисе кадров и, в общем, нужно лепить какой-то большой снежный ком не из снега. Окей, если прям вопрос с отчётами, можно будет заводить какие-то консолидированные хранилища и все системы будут туда сливать данные, но вот при обычном использовании вам всё равно потребуется делать большие джоины, какие с этим косяки я примерно описал.
По варианту общих сервисов, я за него из-за простоты:
Хранить строки подключений нужно в каждом проекте - это не проблема
Дублировать бизнес-логику не нужно, выносите её так же в общие сервисы
Обновлять будет нужно оба сервера, если в общем сервисе баг. Тут разговор, очевидно, про "баг на проде" - из-за общего кода будет баг на обоих продакшенах. Окей, как часто у вас возникают такие ситуации и насколько долго обновить два прода вместо одного?
Ответ написан
Griboks
@Griboks Куратор тега C#
Только одна система, и больше никак! Во всяком случае со стороны пользователя. Если говорить про реализацию, то лучше исходить из особенностей компании и систем. Обычно в качестве переносчиков данных между системами являются менеджеры, которые только этим и занимаются и получают за это деньги.
Если по-умному, то нужно расслоить системы на компоненты, затем объединить одинаковые компоненты (например, бд) в один+продумать грамотное API, удобное для всех систем.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы