API-шлюз и маршрутизация
1) Роль API-шлюза в архитектуре
API-шлюз — L7-компонент на границе (edge), который:- принимает входящий трафик (HTTP/HTTP2/HTTP3, WebSocket, gRPC);
- маршрутизирует по правилам (host/path/headers/method/query/geo/весу/здоровью);
- применяет сквозные политики: аутентификация/авторизация, rate limiting, WAF, CORS, кеширование;
- выполняет трансформации (нормализация заголовков/тел, gRPC↔JSON, GraphQL stitching);
- обеспечивает устойчивость (timeouts, retries, circuit-breaker, outlier detection);
- дает наблюдаемость и биллинг (логи, метрики, трассировки, квоты);
- изолирует внутреннюю топологию (service mesh, приватные сервисы).
Часто используется в паре: Edge/API-Gateway + Ingress/Mesh (Envoy/Istio/Linkerd) — первый решает внешнюю политику, второй — east-west.
2) Типовые топологии
Единый глобальный шлюз (CDN/edge POP → L7 gateway → сервисы) — просто, централизованные политики.
Региональные шлюзы (per-region) + умная маршрутизация по гео/латентности.
Multi-tenant: выделенные маршруты/поддомены/ключи, квоты и лимиты на арендатора.
Hybrid: on-prem + cloud, private link/peering, частные бэкенды за API-шлюзом.
3) Правила маршрутизации L7
Критерии:- Host/Path: `api.example.com` → `/v1/orders/`.
- Headers: `X-Client`, `X-Region`, `User-Agent`, `Accept`.
- Method/Content-Type: различение JSON/Proto/GraphQL.
- Query/Fragment: осторожно — влияет на кеш/варианты.
- Geo/Latency: ближайший POP/регион, failover при деградации.
- Weighted/Canary: распределение трафика 90/10, 50/50, sticky по cookie.
- Session affinity: hash-based по ключу/токену (аккуратно при масштабировании).
yaml nginx. ingress. kubernetes. io/canary: "true"
nginx. ingress. kubernetes. io/canary-weight: "10" # 10% traffic to new backend
Пример (Envoy, header-based routing):
yaml match: { prefix: "/orders", headers: [{name: "X-Experiment", exact_match: "new"}] }
route: { cluster: orders-v2 }
4) Протоколы и совместимость
REST/JSON — дефолт, описывайте OpenAPI для валидации/генерации клиентов.
gRPC — бинарный Proto поверх HTTP/2; для внешних клиентов используйте gRPC-JSON transcoding.
GraphQL — агрегирует сервисы; на периметре контролируйте complexity/ глубину запросов.
WebSocket/SSE — двунаправочно/пуш; учитывайте sticky и timeouts.
HTTP/2/3 (QUIC) — мультиплексирование/быстрый старт; проверьте совместимость с WAF/прокси.
5) Безопасность: аутентификация и авторизация
5.1 Транспорт
TLS 1.2+ на периметре, HSTS, OCSP stapling, PFS.
mTLS для B2B/внутренних API и машин-к-машине.
IP allowlist/denylist, гео-ограничения.
5.2 Прикладной уровень
OAuth2/OIDC: bearer-токены JWT, проверка подписи/экспирации/аудитории.
HMAC/подписи: дата + канонизованная строка + подпись (AWS-подобно) — защита от подмены, повтора (nonce/тайм-окно).
API-ключи: только как идентификатор; права — через RBAC/ABAC/скоупы.
CORS: явные allow-origin, пре-флайт кеш.
WAF: сигнатуры (OWASP API Top 10), анормалия, бот-защита, рекурсивные JSON-поля.
DDoS/Abuse: connection limiting, token-bucket/Leaky bucket, берст + средняя скорость, динамические баны.
yaml plugins:
- name: oidc config: { issuer: "...", client_id: "...", client_secret: "...", scopes: ["orders. read"] }
- name: rate-limiting config: { minute: 600, policy: local }
6) Валидация, трансформации и совместимость
Схемы: валидация тела/заголовков/параметров по OpenAPI/JSON-Schema/Protobuf.
Трансформации: нормализация полей, маскирование PII, добавление корреляционных заголовков (`traceparent`, `x-request-id`).
Версионирование: `Header: X-API-Version`, префиксы `/v1`, ресурсо-версионирование; deprecation policy и Sunset.
Backward-compat: только add-поле; избегайте «ломающих» изменений без новой версии.
Idempotency: `Idempotency-Key` для POST; gateway хранит ключи в Redis с TTL.
7) Устойчивость: политики соединений
Timeouts: connect/read/write; разумные дефолты (например, 1s/5s/5s).
Retries: только для безопасных и идемпотентных; джиттер, exponential backoff, максимум попыток.
Circuit breaker: открывать при ошибках/латентности; half-open для проб.
Outlier detection: выведение плохих инстансов из пула.
Bulkhead/конкуренция: лимиты на одновременные запросы per-route.
Failover: активный/пассивный, зональная деградация.
Shadow traffic: «серый» прогон V2 параллельно V1 (без влияния на ответ) для сравнения.
yaml circuit_breakers:
thresholds:
- priority: DEFAULT max_connections: 1024 max_pending_requests: 2048 max_retries: 3
8) Кеширование и производительность
HTTP-кеш: `Cache-Control`, `ETag/If-None-Match`, `Vary`, `stale-while-revalidate`.
Edge-кеши/POP: CDN для статики и «кешируемых» API (идемпотентные GET).
Compression: `gzip/br` (не сжимайте уже сжатое).
Request collapsing («coalescing»): объединение идентичных параллельных запросов.
Response shaping: поля/фильтры, пагинация (cursor-based), лимиты размеров.
9) Наблюдаемость и эксплуатация
Метрики: `l7_req_total{route,method,code}`, `latency_ms{p50,p95,p99}`, `upstream_errors`, `retry_count`, `cb_state`, `429_rate`, `quota_usage{tenant}`.
Логи: структурные, с `trace_id/span_id`, `user_id/tenant_id`, `client_ip`.
Трейсы: W3C Trace Context (`traceparent`, `tracestate`), пропагируйте в апстримы.
Аудит: кто вызывал что, с какими правами; неизменяемые хранилища для чувствительных API.
SLO/SLA: целевые p99, бюджет ошибок; роут-уровень лучше, чем глобальный.
10) Управление планом пропускной способности
Quota per-tenant/ключ/пул клиентов, в мин/час/сутки.
Burst + sustained лимиты; leaky bucket для сглаживания.
Fairness: при перегрузе — fair queuing вместо «первого встретившегося».
Приоритеты: системные/критичные маршруты с приоритетом и выделенными пулами.
11) Управление изменениями и релизы
Canary/Blue-Green: весовая маршрутизация; автоматическое продвижение по SLO (ошибки/латентность).
Feature gates/бэкенд-флаги: включение по заголовку/токену.
Shadowing/дифф-валидаторы: сравнение тел/статусов, допуски по дельте.
Стейджинги: выделенные домены/пути (`staging.api…`), отдельные ключи и квоты.
12) Примеры конфигураций
12.1 NGINX — базовый gateway с лимитом и кешем
nginx map $http_x_request_id $reqid { default $request_id; }
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
server {
listen 443 ssl http2;
server_name api. example. com;
security add_header Strict-Transport-Security "max-age = 31536000" always;
location /v1/ {
limit_req zone=perip burst=30 nodelay;
proxy_set_header X-Request-ID $reqid;
proxy_set_header Authorization $http_authorization;
proxy_connect_timeout 1s;
proxy_read_timeout 5s;
proxy_cache api_cache;
proxy_cache_valid 200 10s;
proxy_cache_use_stale error timeout updating;
proxy_pass http://orders-v1;
}
}
12.2 Envoy — маршрутизация по весам и ретраи
yaml routes:
- match: { prefix: "/orders" }
route:
weighted_clusters:
clusters:
- name: orders-v1 weight: 90
- name: orders-v2 weight: 10 retry_policy:
retry_on: "5xx,reset,connect-failure"
num_retries: 2 per_try_timeout: 2s
12.3 Traefik — мидлвари и хедеры
yaml http:
middlewares:
secHeaders:
headers:
stsSeconds: 31536000 contentTypeNosniff: true routers:
api:
rule: "Host(`api. example. com`) && PathPrefix(`/v1`)"
service: svc-orders middlewares: ["secHeaders"]
13) Анти-паттерны
Один глобальный лимит на всех — «добрые соседи» страдают из-за «шумных».
Ретраи без идемпотентности → дубли эффектов (платежи, создание сущностей).
Игнорирование `timeout`/`max body size` → зависания/исчерпание воркеров.
Смешивание edge-политик и бизнес-логики в шлюзе (утяжеление периметра).
Отсутствие валидации схем → хрупкость клиентов и «ломающие» релизы.
Голый WebSocket без учета auth/лимитов/idle-тайма.
Секреты в заголовках без ротации; отсутствие mTLS в внутренних B2B.
14) Тест-плейбуки (Game Days)
Шторм запросов: проверка limiter/quota, 429-поведение, деградация.
Потеря одного кластера: failover/перераздача веса; SLO канареек.
Утяжеленные ответы: max body/timeouts; обрубание соединений.
Инъекции/аномалии: WAF-правила, запрет рекурсивных JSON, большие глубины GraphQL.
Сбой трассировки: проверка пропагации `traceparent` и семплирования.
Секреты: ротация ключей/JWKS, истечение токенов, clock-skew допуск.
15) Чек-лист внедрения
- Определены домены/пути/версии, опубликована OpenAPI/Proto.
- Настроены TLS/mTLS, HSTS, секрет-менеджмент и ротация.
- Включены аутентификация (OIDC/HMAC), RBAC/скоупы, CORS.
- Лимиты/квоты per-tenant, справедливые очереди, 429-UX.
- Маршрутизация по весам/заголовкам, план канареек и rollback.
- Политики timeout/retry/circuit-breaker/outlier.
- Валидация схем, трансформации, маскирование PII.
- Edge-кеш/ETag, coalescing, gzip/br.
- Наблюдаемость: метрики, логи, трассы, дашборды и алерты.
- Runbooks: инциденты, ротация ключей, блок-листы, «черная пятница».
16) FAQ
Q: Чем API-шлюз отличается от сервис-меша?
A: Шлюз — north-south (внешний периметр, сквозные политики). Меш — east-west (внутрикластерная связность/MTLS/ретраи). Часто используются вместе.
Q: Где реализовывать auth: в шлюзе или сервисах?
A: Оба уровня: шлюз — coarse-grained (аутентификация, базовые права/квоты), сервис — fine-grained (доменные роли/атрибуты).
Q: Когда нужен gRPC-JSON transcoding?
A: Когда внутренний gRPC, а наружу требуется REST/JSON и простые клиенты/браузеры.
Q: Как выбирать стратегию версионирования?
A: Для публичных API — путь `/vN` + заголовки депривации и долгий overlap. Для внутренних — capability-флаги/схема совместимости.
17) Итоги
API-шлюз — не просто «проксик», а центр политик и устойчивости. Правильная маршрутизация, безопасность, лимиты, валидация и наблюдаемость дают предсказуемость и скорость релизов. Комбинируйте edge-шлюз с сервис-мешем, автоматизируйте канарейки и квоты, тестируйте сбои — и периметр станет вашим ускорителем, а не бутылочным горлышком.