Когда внутренний API-шлюз действительно помогает
API-шлюзы стандартны на публичном периметре. Вопрос о том, нужен ли он между собственными внутренними сервисами, менее очевиден и заслуживает отдельного разбора.
Большинство компаний добавляют API-шлюз, когда открывают сервисы внешнему миру. Это разумный выбор по умолчанию. Внутренняя сторона - нужно ли маршрутизировать трафик между собственными сервисами через единый шлюз - получает значительно меньше внимания и заслуживает отдельного рассмотрения.
Я видел обе ошибки. Компания с пятью сервисами и без шлюза, утопающая в разношёрстных схемах аутентификации и дублирующихся логах. И команда с двадцатью сервисами, внедрившая шлюз слишком рано, получившая единую точку отказа, и потратившая два квартала на распутывание. Ответ не универсален, но критерии решения - вполне конкретны.
Что шлюз реально делает внутри
На периметре шлюз занимается авторизацией, ограничением запросов и трансляцией протоколов для внешних вызовов. Внутри вам обычно нужны три вещи: единое место для аутентификации между сервисами, центральная точка для наблюдаемости (логи запросов, задержки, частота ошибок) и способ маршрутизировать трафик, не прописывая топологию в каждом сервисе.
Ничего из этого не требует шлюза в небольшой системе. Это становится по-настоящему болезненным, когда независимо деплоируемых компонентов набирается больше десяти.
Где шлюз даёт реальную ценность
Самый чёткий сигнал - расползание схем аутентификации. Если каждая команда сделала свою валидацию токенов, рано или поздно случится инцидент, который затронет их все одновременно. Централизация этой логики в шлюзе - даже тонком - означает, что один фикс распространяется везде.
Второй сигнал - наблюдаемость. Когда каждый сервис пишет логи по-своему, разобрать инцидент по пяти шагам занимает часы. Шлюз, добавляющий trace ID и логирующий параметры запроса на каждом внутреннем переходе, даёт это практически без усилий со стороны отдельных сервисов.
Третий - скрытие топологии. Сервисы, обращающиеся друг к другу по прямым именам DNS, становятся привязанными к деталям деплоя. Шлюз позволяет переименовать, перенести или разделить сервис, не обновляя каждого вызывающего.
Где он создаёт лишнюю сложность
Если сервисов мало, они хорошо понятны и принадлежат одной-двум командам - шлюз это абстракция в поисках проблемы. Вы добавляете сетевой хоп, новый компонент для эксплуатации, новую точку отказа и новую вещь, которую нужно изучить - без соразмерной пользы.
То же самое, если ваша реальная проблема - не сквозные технические заботы, а владение данными или ясность процессов. Шлюз их не исправит. Он сделает их чуть менее заметными.
Простой тест для принятия решения
Прежде чем рекомендовать внутренний шлюз, я обычно задаю три вопроса:
- Сколько разных схем аутентификации существует между сервисами сегодня?
- Сколько времени уходит на восстановление цепочки запроса по логам?
- Как часто сервисам нужно обновлять список вызывающих, когда зависимость переезжает?
Если ответы - «несколько», «долго» и «регулярно» - шлюз оправдывает себя. Если ответы «пока не проблема» - подождите, пока станет. Внедрять раньше времени значит поддерживать два набора конфигурации вместо того, чтобы пользоваться одним.
Практическая отправная точка
Если решение принято - начинайте узко. Возьмите одну функцию, обычно авторизацию или трассировку, и докажите ценность там, прежде чем расширяться. Худшие внутренние шлюзы, которые я видел, пытались решить всё сразу и превращались во второй сервер приложений с непонятным владельцем.
Шлюз - это инфраструктура. Как и любая инфраструктура, он должен быть скучным в эксплуатации и невидимым в работе. Если ваша команда говорит о шлюзе больше, чем о сервисах, которые он соединяет, - что-то пошло не так при определении его задач.