Описание подхода к проксированию запросов через монолитную систему при переходе на микросервисную архитектуру.
В статье «От монолита к микросервисам» приведен пример того, как и для чего перестать развивать легаси-монолит, выделяя новую функциональность в отдельный сервис и направляя трафик посредством API Gateway на этот сервис.
Эта схема проста и понятна до тех пор, пока мы не столкнемся с реальностью.
Рассмотрим пример. Монолитная система, посредством кототой можно получить чертеж любой части самолета в нескольких форматах (точная геометрия, легковесная pdf). Права доступа определяются на основе роли пользователя, страны и множества других параметров, например: Export Control на основе ITAR, ECCN и EAR-кодов), тип/формат документа, тип детали, да еще и в связке с номером самолета, владельцем и так далее. Логика сложная и запутанная.
Первый «микросервис» может быть предельно простым, каким он и должен быть. Скорее всего его напишет один или пара энтузиастов и он будет делать что-то тривиальное.
Идея хорошая, появляются знания об организации процесса поставки, разбивается стена страха неизвестности, появляется мотивация, тут может появиться проксирующий запросы шлюз и энтузиасты предлагают вынести в отдельные микросервисы что-нибудь посложнее. Сервис, возвращающий точную геометрию, например. Ведь это сулит невероятные выгоды: независимая поставка, использование подходящих технологий, горизонтальное масштабирование при росте нагрузки, удобная балансировка…пока не выясняется, что «права доступа определяются на основе…», «все обращения должны быть зафиксированы…». Казалось бы — пусть API Gateway этим и займется, безопасность — это сквозная функциональность до определенного уровня, но логика ровным слоем размазана по всему монолиту, её вычленение займет уйму времени.
Как быть?
Предусловия
С помощью первых, простых сервисов, компания учится выполнению предусловий для микросервисной архитектуры, сформулированных Мартином Фаулером:
- Быстрое создание новых окружений
- Простой, но не примитивный, мониторинг
- Быстрый и надежный процесс поставки
Phil Calçado (Meetup, в прошлом DigitalOcean и SoundCloud) расширил список предусловий, добавив следующие:
- Быстрое расширение/создание хранилищ данных
- Легкий доступ к границам систем
- Аутентификация/авторизация
- Стандартизированный RPC
И мы получаем первую проблему: получить доступ извне во внутреннюю сеть оказывается не так просто.
Не масштабируется!
Проксирование API Gateway на ранних этапах и для простых сервисов работает не плохо. Но это решение не масштабируется. Фиче-тогглинг, авторизация, аутентификация, логирование и прочая сквозная функциональность реализованы в монолите и сильно связаны с основной бизнес-логикой. Перенос этой логики в шлюз может потребовать титанических усилий.
Что делать?
Предлагается на первых порах использовать в качестве прокси сам монолит:
При этом среди задач технического долга появляется «Рефакторинг авторизации и аутентификации» с целью выделения этой функциональности в отдельный пакет и последующим выделением в отдельный сервис, после чего можно переходить с целевой картинке с реализацией сквозной функциональности по безопасности на уровень API Gateway.
На какое-то время всё станет сложнее: при изменении сервисов может потребоваться поставка и монолитного приложения.
О чем не забыть?
Помимо безопасности в монолитном легаси размазанной и сильно связанной может быть следующая сквозная функциональность, что может привести к еще большим трудностям при использовании API Gateway в качестве прокси на первых порах:
- Логирование (отдельные части приложения могут писать логи в собственном формате в различные файлы.
- Механизмы инструментирования кода и сбора метрик
- Уведомления об ошибках
- Трассировка запросов (сквозная идентификация бизнес-транзакции)
- Методы проверки работоспособности (HealthCheck)
- Внешнее конфигурирование
Со временем все это следует привести к единому стандарту и сделать частью микросервисного фреймворка, общего для всех сервисов. Как это согласуется с тем, что каждый сервис можем использовать свои собственные технологии? Java, Ruby, Go? Под каждый язык придется поддерживать свою реализацию, обеспечивающую стандартное поведение: если мы договорились, что пишем логи в определенном формате в syslog, то все сервисы следуют этим договорённостям.
Подводя итог
Неявная цель этой статьи — показать, что практически у любой проблемы есть как минимум два возможных решения, а выбор зависит от конкретного контекста и компромиссов, на которые готова пойти компания. Большая часть статей и книг описывают именно подход с использованием API Gateway, что хорошо подходит для новых систем, но может не подойти к разросшимся монолитным системам и иногда переход от монолита к микросервисам может стать даже более увлекательным, чем построение микросервисной архитектуры с чистого листа.
1 comment / Add your comment below