.NET Tutorial
Middle6 мин чтенияВопрос 11 из 17

API Gateway pattern — зачем нужен?

Проблема без шлюза

Веб-клиент

orders.example.uz

catalog.example.uz

payments.example.uz

Мобильное приложение

users.example.uz

Каждый сервис сам проверяет токены,
настраивает CORS, rate limiting;
клиент знает внутреннюю топологию;
экран = 5 запросов с телефона

Веб-клиент

orders.example.uz

catalog.example.uz

payments.example.uz

Мобильное приложение

users.example.uz

Каждый сервис сам проверяет токены,
настраивает CORS, rate limiting;
клиент знает внутреннюю топологию;
экран = 5 запросов с телефона

Клиенты обращаются к сервисам напрямую

Со шлюзом

/api/orders/*

/api/catalog/*

/api/payments/*

gRPC

Веб-клиент

API Gateway
TLS, аутентификация,
rate limit, маршрутизация,
агрегация, логирование

Мобильное приложение

Партнёры

Orders

Catalog

Payments

Users

/api/orders/*

/api/catalog/*

/api/payments/*

gRPC

Веб-клиент

API Gateway
TLS, аутентификация,
rate limit, маршрутизация,
агрегация, логирование

Мобильное приложение

Партнёры

Orders

Catalog

Payments

Users

Единая точка входа

Функции шлюза

Функция Зачем
Маршрутизация Скрыть внутреннюю топологию, менять её без изменения клиентов
Аутентификация Проверить JWT один раз; сервисы получают уже проверенный контекст (или тоже проверяют — zero trust)
Rate limiting / квоты Защита от злоупотреблений, тарифные планы для партнёров
Агрегация Один запрос клиента → несколько внутренних, один ответ (экономия запросов с мобильной сети)
Трансляция протоколов Внешний REST/JSON → внутренний gRPC
Кросс-срезы CORS, сжатие, заголовки безопасности, кэш, correlation id, логирование
Версионирование и canary /v1 и /v2, процент трафика на новую версию

Агрегация

DeliveryCatalogOrdersGateway / BFFМобильноеприложениеpar[параллельно]GET /mobile/orders/42GET /orders/42GET /products?ids=...GET /shipments?order=42заказназвания и фотостатус доставкиодна модель под экран
DeliveryCatalogOrdersGateway / BFFМобильноеприложениеpar[параллельно]GET /mobile/orders/42GET /orders/42GET /products?ids=...GET /shipments?order=42заказназвания и фотостатус доставкиодна модель под экран
Экран «Карточка заказа» одним запросом

Одна мобильная round-trip вместо трёх — заметная экономия на медленной сети. Но агрегация — это уже логика; при её росте её лучше держать в BFF, а не в общем шлюзе.

BFF — Backend for Frontend

SPA

Web BFF
cookie-сессия, токены на сервере

iOS / Android

Mobile BFF
компактные ответы, агрегация

Партнёры

Public API Gateway
ключи, квоты, SLA

Микросервисы

SPA

Web BFF
cookie-сессия, токены на сервере

iOS / Android

Mobile BFF
компактные ответы, агрегация

Партнёры

Public API Gateway
ключи, квоты, SLA

Микросервисы

Шлюз под каждый тип клиента

BFF принадлежит команде клиента и меняется вместе с ним; общий шлюз не превращается в «свалку» частных потребностей всех клиентов. Web-BFF также решает задачу безопасности: токены OAuth не хранятся в браузере.

YARP

appsettings.json
{
  "ReverseProxy": {
    "Routes": {
      "orders":  { "ClusterId": "orders",  "AuthorizationPolicy": "default", "RateLimiterPolicy": "per-user",
                   "Match": { "Path": "/api/orders/{**rest}" }, "Transforms": [ { "PathPattern": "/orders/{**rest}" } ] },
      "catalog": { "ClusterId": "catalog", "Match": { "Path": "/api/catalog/{**rest}" } }
    },
    "Clusters": {
      "orders":  { "LoadBalancingPolicy": "RoundRobin",
                   "HealthCheck": { "Active": { "Enabled": true, "Path": "/health/ready" } },
                   "Destinations": { "o1": { "Address": "http://orders-1:8080" }, "o2": { "Address": "http://orders-2:8080" } } },
      "catalog": { "Destinations": { "c1": { "Address": "http://catalog:8080" } } }
    }
  }
}
Program.cs шлюза
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(o => o.Authority = "https://auth.example.uz");
builder.Services.AddAuthorization();
builder.Services.AddRateLimiter(o => o.AddTokenBucketLimiter("per-user", t => { t.TokenLimit = 100; t.TokensPerPeriod = 50; t.ReplenishmentPeriod = TimeSpan.FromSeconds(10); }));
builder.Services.AddReverseProxy().LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.UseRateLimiter();
app.MapReverseProxy();
app.Run();

YARP — это обычное приложение ASP.NET Core: весь конвейер middleware, DI, OpenTelemetry, собственные трансформации на C#.

API Gateway и Service Mesh

API Gateway Service Mesh (Istio, Linkerd)
Трафик Север-юг: снаружи внутрь Восток-запад: сервис ↔ сервис
Где На границе системы Sidecar-прокси рядом с каждым сервисом
Функции Аутентификация клиентов, квоты, агрегация, публичный API mTLS, ретраи, балансировка, телеметрия между сервисами

Они дополняют друг друга.

Риски и анти-паттерны

  • Единая точка отказа: несколько реплик шлюза за балансировщиком, health checks, автомасштабирование.
  • Бизнес-логика в шлюзе: шлюз меняется при каждой фиче — снова монолит. Шлюз — инфраструктура; логика — в сервисах или BFF.
  • Один шлюз на все команды: узкое место для изменений. Декларативная конфигурация (маршруты в репозиториях сервисов) или BFF решают.
  • Дополнительная задержка — небольшая (миллисекунды), но для цепочек стоит учитывать.

Вопросы на засыпку

Нужно ли сервисам проверять токен, если его уже проверил шлюз?

В модели zero trust — да: внутренняя сеть не считается доверенной, и сервис проверяет токен (дёшево — подпись и claims) или использует mTLS + передачу пользовательского контекста. Минимум — сервисы не должны быть доступны снаружи в обход шлюза.

Чем API Gateway отличается от обычного reverse proxy или балансировщика?

Reverse proxy (NGINX) и балансировщик распределяют трафик на уровне HTTP/TCP. API Gateway — reverse proxy с функциями управления API: аутентификация, квоты, агрегация, трансформации, аналитика, портал разработчика. Граница размыта: YARP и NGINX можно дорастить до шлюза.

Что такое Kubernetes Gateway API?

Стандартизированное расширение Ingress в Kubernetes с ролями (инфраструктура / маршруты команд), маршрутизацией HTTP и gRPC, разделением трафика. Реализуется контроллерами Envoy Gateway, Istio, NGINX и другими — часто заменяет отдельный шлюз для маршрутизации.

Как шлюз помогает при миграции монолита?

Шлюз — естественная точка паттерна Strangler Fig: новые эндпоинты маршрутизируются в новый сервис, остальные — в монолит. Клиенты не замечают перехода.

Итог

API Gateway даёт клиентам единую точку входа и централизует кросс-срезы: маршрутизацию, аутентификацию, лимиты, агрегацию. BFF подстраивает API под конкретный клиент. Держите шлюз тонким и отказоустойчивым, бизнес-логику — в сервисах, а для межсервисного трафика используйте service mesh или устойчивые клиенты.