Как заставить системы общаться
опубликовано: ⏰ 9Немного об интеграциях в “кровавом” и не очень энтерпрайзе. В основном это обзорная статья без детального погружения в технические аспекты и примеры реализации решений. Постараюсь дать общее представление о том, какие подходы интеграций существуют, какие проблемы возникают при их использовании.
Общее описание по EIP (Enterprise Integration Patterns) можно найти на сайте enterpriseintegrationpatterns.com.
Введение
Интеграция – это процесс объединения различных систем и сервисов для обеспечения эффективного обмена данными и взаимодействия между ними.
Если отбросить технические детали реализации, то можно выделить несколько подходов организации обмена между системами:
- Удалённый вызов процедур (RPI/RPC) – взаимодействие, где одна система вызывает метод другой системы через некий API с известным контрактом.
- Сообщения – взаимодействие через обмен небольшими сообщениями между двумя системами, используя, например, брокеры сообщений или их аналоги.
- Передача файлов – обмен данными через файлы, расположенные на общем сетевом ресурсе или через распределённые файловые системы.
- Общая база данных – обмен данными, хранящимися в общей базе данных, доступной для нескольких систем.
Удалённый вызов процедур (RPI)
В большинстве случаев, это синхронное взаимодействие по своей сути – запрос и ответ. Хотя после выполнения запроса (установки соединения), одна или обе стороны могут продолжить работу в асинхронном режиме. Как пример – gRPC Streaming, WebFlux.
Используются в случаях:
- Требуется получение ответа на запрос немедленно или в короткий срок.
- Когда очереди слишком дорого и сложно или необходимо пересматривать архитектуру существующих приложений.
- Практически любое клиент-серверное взаимодействие для десктоп/веб-приложений. Хотя можно и к очередям из браузера в случае с NATS, через WebSockets.
- “У нас старая система – переделывать не будем”.
Примеры протоколов:
В чём плюсы такого подхода:
- Простота, так как это наверное самый привычный и понятный подход для вызова функции во внешней системе (P2P), по аналогии с вызовом процедур в коде.
- Получаем ответ сразу после запроса, без необходимости использования статусов/состояний для запросов и ожидания ответа.
- Использование предопределённых контрактов для API, которые описываются в формате используемого протокола, например:
- OpenAPIv3 для REST API.
- Protocol Buffers для gRPC.
В чём минусы такого подхода:
- Возможные проблемы с задержками (latency) на больших объёмах данных или высокой частоте запросов. Упираемся в аппаратные ограничения сети, процессора, памяти и т. д.
- Относительно низкая доступность систем. Отказ системы ведёт к отказу в обработке вызовов, что в свою очередь должно корректно обрабатываться на стороне клиента. Естественно, для повышения доступности строятся кластеры и настраиваются балансировщики нагрузки, но не всегда и не везде, к сожалению.
- Синхронные вызовы блокируют ресурсы на стороне клиента и на стороне сервера до завершения вызова.
Сообщения
Используется для асинхронного взаимодействия. Хотя встречались схемы с попыткой сделать его синхронным, через блокирующие ожидания ответов на клиенте.
В основном применяется, там где не требуется ответ сразу:
- Быстрого ответа не требуется и можно организовать межсервисное взаимодействие асинхронно.
- Операции выполняются довольно продолжительное время и не хочется блокировать ресурсы.
- Для потоковой обработки больших объёмов данных (ETL/Data Streaming).
Примеры брокеров сообщений:
В чём плюсы такого подхода:
- Отсутствие блокировок на стороне клиента и сервера, низкие задержки.
- Поддержка гарантированной доставки сообщений с подтверждением получения.
- В общем случае, возможность простого масштабирования производительности обработки сообщений за счёт добавления новых потребителей или продюсеров сообщений.
- Высокая доступность системы за счёт репликации очередей, развёртывания в кластере.
- Так же как и с RPI есть возможность описывать формат сообщений, а также контракт взаимодействия. Примеры:
- AVRO
- JSON Schema
- AsyncAPI – аналог OpenAPIv3, но для асинхронных API.
В чём минусы такого подхода:
- Повышается сложность системы из-за использования подхода с асинхронным взаимодействием. В случае EDA необходимо более тщательно продумывать, как её компоненты будут обмениваться данными и менять своё состояние.
- Не всегда так просто взять и настроить брокер сообщений, каждый со своими проблемами и особенностями:
- Зависимость от аппаратной составляющей – падающие и выходящие из строя сервера, низкая производительность сети и т. д.
- Зависимость от программной составляющей – отдельная головная боль, это различные баги и проблемы в самих брокерах, клиентских библиотеках, отсутствие необходимой функциональности (например, надёжной репликации между узлами брокера).
- Относительно высокая сложность в настройке и поддержке всех компонентов системы.
Передача файлов
Некий вариант асинхронного взаимодействия. Кладём один файл в каталог, а другая система когда-нибудь его заберёт и возможно положит файл с ответом.
Может быть использовано для:
- Обмена файлами между старыми системами, когда нет возможности доработать и добавить новое API.
- Передачи больших файлов, когда их передача через другие каналы может нести большие накладные расходы. Например, в случае использования брокеров сообщений, файлы обычно выгружаются на диск, а затем ссылка на них передаются в сообщении.
Примеры:
В чём плюсы такого подхода:
- Простой в реализации и понимании способ обмена. Кладём файл (с индикацией блокировки на время операции), другая система забирает и обрабатывает.
- Относительная хорошая надёжность хранения данных, если хранилище построено с учётом отказоустойчивости и права доступа к ней ограничены.
В чём минусы такого подхода:
- Разнородность форматов файлов, так как выгрузить могут всё что угодно. Необходимо проверять целостность и полноту данных обработкой.
- Довольно легко потерять данные, вариации на тему
rm -rf /. - Возможно сейчас с SSD/NVME дисками и не минус вовсе, но при больших объёмах передаваемых данных диски могут стать узким местом по IOPS.
- Низкая отказоустойчивость в большинстве случаев. На практике, не так часто готовы вкладывать ресурсы человеческие и финансовые в развёртывание распределённых файловых систем, используют обычные сетевые (NFS/SMB) со всеми их сопутствующими проблемами.
Общая база данных
Синхронное взаимодействие или асинхронное – смотря с какой стороны посмотреть. Если выполнение операции DML/DDL, то наверное синхронное. Если с точки зрения обмена данными через таблицы, то похоже на асинхронное. Да и некоторые СУБД поддерживают подписки на события в СУБД (PostgreSQL LISTEN)
Может быть использовано для:
- Как и в случае с передачей файлов - обмен данными между старыми системами, когда нет возможности доработать и добавить новое API.
- Обработка событий, которые нельзя добавить в существующую систему (например, устаревшая замещаемая система, больше не поддерживается и не разрабатывается). Отдельный сервис отслеживает изменения в таблицах и выполняет определённые действия, такие как отправка уведомлений или обновление данных в другой системе.
- Общие данные в двух и более системах. Да, это плохая практика и нарушает изоляцию, но такое тоже возможно.
В чём плюсы такого подхода:
- Отсутствие необходимости дорабатывать существующие системы, когда необходимо получить прямой доступ к их оперативным данным.
- Не требуется доработок API, усложнения инфраструктуры (ФС, брокеры и прочее).
В чём минусы такого подхода:
- Нарушение изоляции данных, что может привести к проблемам при изменении модели данных со стороны одной из систем.
- Сложность поддержки и отладки, так как данные могут быть изменены несколькими системами одновременно.
- Потенциальные проблемы с согласованностью данных, особенно если изменения происходят одновременно в нескольких системах.
- Проблемы с безопасностью, доступ к данным имеет все системы, нужен дополнительный контроль.
Сервисная шина предприятия (ESB)
Отдельно стоит упомянуть сервисные шины предприятия (ESB).
ESB - связующее программное обеспечение, обеспечивающее централизованный и унифицированный событийно-ориентированный обмен сообщениями между различными информационными системами на принципах сервис-ориентированной архитектуры.
ESB зачастую могут объединять в себе несколько подходов к интеграции. Они часто используются для обеспечения централизованного управления процессами взаимодействия между различными системами. То есть в гетерогенных средах (SOA, MSA), где один сервис написан на C# (SOAP), другой - на Java (REST) и третий - на Node.js (GraphQL). ESB может взять на себя роль посредника и обеспечить единообразный интерфейс взаимодействия между ними, скрыв особенности реализации API каждого из сервисов.
Здесь подробно не буду расписывать их плюсы и минусы, это лучше сделать в отдельной статье. Но стоит отметить, что ESB хотя и потеряла в популярности, уступив интеграционным микросервисам (возможно им есть правильное название, я их зову так :), но все ещё используются.
ETL
Нельзя не упомянуть и инструменты для организации ETL конвейеров. Но вкратце, так как тема довольно обширная.
Наверное, самый известный и популярный из них (для меня по крайней мере :) это Apache Camel. Довольно мощный инструмент, который позволяет создавать маршруты для обработки и трансформации данных между различными источниками и поддерживает все основные EIP.
Второй из них, можно сказать Apache Camel с GUI – Apache NiFi. Он позволяет создавать графические конвейеры для обработки данных и имеет множество возможностей для мониторинга и управления этими конвейерами.
Сюда же можно добавить:
- Apache Flink – распределенная система обработки потоковых данных с высокой производительностью.
- Apache Airflow – платформа для управления рабочими процессами, которая позволяет автоматизировать процессы обработки данных.
Наблюдаемость систем
Отдельно хочется выделить проблемы наблюдаемости интеграционных потоков. Не важно с какими подходами и с использованием каких решений бы они не строились, обеспечение мониторинга, логирования и трассировки является одним из обязательных требований.
Основная проблема при отладке и поддержке интеграционных потоков – это необходимость в понимании происходящих процессов и мониторинге передаваемых данных между системами. То есть необходимо не только видеть логи с каким-то сообщениями, но и понимать сквозной процесс передачи пакета данных из одной системы в другую по всей цепочке участников интеграционного обмена.
Так же важно иметь возможность оценить согласованность и непротиворечивость данных в различных системах, но это решается скорее не мониторингом, а специализированными инструментами для анализа данных.
Напоследок побуду Капитаном Очевидность. Есть один момент, который стоит упомянуть – наблюдатель не должен быть наблюдаемым, как бы странно это не звучало. Это значит, что не нужно делать мониторинг в той же системе, которую необходимо мониторить. Роняем такую систему и теряем её же мониторинг.
Список далеко не полный, но наверное, самые распространённые и известные инструменты из них:
- Мониторинг + логирование
- PLG Stack Prometheus, Grafana, Loki
- ELK Stack Elasticsearch, Logstash, Kibana.
- VictoriaMetrics, VictoriaLogs.
- Jaeger, Zipkin – система распределенной трассировки.
- OpenTelemetry – определенный стандарт, попытка объединить различные инструменты для обеспечения наблюдаемости систем в единую экосистему.
Заключение
Кратко в этот раз. Нет универсального подхода или инструмента, всё зависит от проекта, требований, сроков и ограничений Заказчика. Выбор инструментов должен учитывать всё вводные именно вашего проекта, а не чьи-то абстрактные рекомендации :)