API-шлюз на реальных браузерах для платформы без API

Боевой REST API и флот браузерных воркеров в Kubernetes перед крупной потребительской веб-платформой, у которой нет публичного API.

Область
Интеграции и автоматизация
Наша роль
Реверс-инжиниринг, архитектура, бэкенд-разработка, DevOps и сопровождение
Год
2025-2026

Мы сделали стабильный документированный REST API для бизнеса, чьи операции завязаны на крупную потребительскую веб-платформу без публичного API. Платформа подписывает запросы VM-обфусцированным JavaScript-шифрованием прямо на странице и закрыта WAF и антибот-защитой, поэтому шлюз выполняет каждый вызов в настоящей браузерной сессии Playwright. Флот браузерных воркеров в Kubernetes под управлением Temporal асинхронно ведёт онбординг аккаунтов, активацию кодов и заказы на пополнение, мониторинг встроен.

Задача

  • Бизнес клиента зависел от сторонней платформы без партнёрского API: поиск профиля, проверка и активация кодов, заказы на пополнение — всё это доступно только через сайт.
  • Сайт собирает и подписывает запросы VM-обфусцированным JavaScript-шифрованием: логику исполняет байт-код-интерпретатор, встроенный в страницу, и обычный HTTP-клиент не может сформировать валидный вызов.
  • WAF и антибот-защита отсекают трафик, который не похож на цельную браузерную сессию, а правила риск-контроля со временем меняются.
  • Для операций нужны авторизованные сессии: их надо создавать, проверять, обновлять и выводить из оборота, и каждая привязана к сетевому маршруту нужного региона.
  • Партнёрам нужен стабильный контракт, идемпотентная отправка заказов, предсказуемое время ответа на чтение и понятные финальные статусы — при том что платформа меняется без предупреждения.

Решение

Исполнителем у нас работает настоящий браузер, а перед ним стоит аккуратный API. Мы разобрали шифрование платформы настолько, чтобы понять, как формируются запросы, и сознательно не стали его переписывать: шлюз вызывает собственный код подписи платформы внутри «тёплых» браузерных сессий. Так интеграция проходит те же шаги, что и браузер обычного пользователя, и не ломается, когда защиту пересобирают. Шлюз на FastAPI отвечает на быстрые запросы из пула браузерных контекстов на одном общем Chromium в поде. Долгие операции идут как workflow в Temporal на отдельном флоте воркеров, с повторами и бюджетом времени. В PostgreSQL лежат аккаунты, сессии и пул маршрутов от нескольких провайдеров, а сервис мониторинга шлёт алерты в командный чат.

Архитектура

Архитектура: API-шлюз на FastAPI с пулом браузерных контекстов, Temporal, четыре типа браузерных воркеров, PostgreSQL и мониторинг
Архитектура: API-шлюз на FastAPI с пулом браузерных контекстов, Temporal, четыре типа браузерных воркеров, PostgreSQL и мониторинг

Что умеет система

Три API
Внутренний, партнёрский и административный API, у каждого своя OpenAPI-документация и API-ключи с ролями. У партнёрского API урезанный и стабильный контракт ответа.
Асинхронные заказы
Заказ принимается с ответом 202 Accepted и необязательным ключом идемпотентности, результат клиент забирает опросом. Для внутренних вызовов есть синхронный вариант.
Быстрое чтение на тёплых контекстах
Поиск профиля и проверка кода — это один вызов на странице в уже готовом браузерном контексте, поэтому ответ приходит примерно за время одного запроса к платформе.
Жизненный цикл аккаунтов и сессий
Онбординг аккаунтов, прогрев и плановое обновление сессий работают как workflow в Temporal, рядом — синхронизация пула маршрутов и очистка логов использования.
Две стратегии активации
Высокопроизводительный конвейер на пуле сессий и последовательный режим, который держит работу за уже сложившимся аккаунтом.
Мониторинг и chat-ops
Алерты о росте очереди, доле ошибок и здоровье маршрутов приходят в командный чат. Оператор включает и выключает провайдеров маршрутов прямо из чата, без передеплоя.

Инженерные решения

  • Пул браузеров переделан после утечки в проде: схема «один процесс на инстанс» оставляла деревья процессов, и мы перешли на один общий Chromium в поде с пулом контекстов, балансировкой по давности использования, проверкой здоровья каждые 15 секунд, мягкой ротацией и fail-fast-выходом, после которого Kubernetes чисто перезапускает под.
  • Цельная браузерная идентичность: каждая сессия живёт под одной идентичностью, прогревается так, как сайтом пользуется живой посетитель, и переиспользует свои cookies. Именно поэтому интеграция стабильно работает за WAF и антибот-защитой.
  • Никаких гонок за общие пулы: аккаунт и маршрут резервируются одной транзакцией с построчной блокировкой и пропуском занятых строк, а транзакции в базе никогда не охватывают внешний I/O.
  • Каждый ответ платформы классифицируется: воркер либо продолжает на той же сессии, либо начинает заново со свежим браузером, аккаунтом и маршрутом. Повторы укладываются в бюджет времени заказа.
  • Каждая задача — отдельный деплоймент в Kubernetes, масштабируемый числом реплик, с shared memory в памяти для Chromium и пробами; схемой данных владеет один сервис, у него 32 версионированные миграции Alembic.

Интерфейс

Схемы

Жизненный цикл асинхронного заказа: от 202 Accepted до финального статуса, с повтором на свежей сессии
Жизненный цикл асинхронного заказа: от 202 Accepted до финального статуса, с повтором на свежей сессии
Развёртывание в Kubernetes: шлюз, воркеры, масштабируемые числом реплик, singleton-мониторинг и Job для расписаний
Развёртывание в Kubernetes: шлюз, воркеры, масштабируемые числом реплик, singleton-мониторинг и Job для расписаний

Стек

  • Python 3.12
  • FastAPI
  • Playwright
  • Chromium
  • Temporal
  • PostgreSQL
  • SQLAlchemy
  • Alembic
  • Docker
  • Kubernetes
  • Traefik
  • S3
  • structlog
  • Locust

Что это показывает

  • Надёжный документированный API поверх платформы, у которой API нет, включая реверс-инжиниринг VM-обфусцированного JavaScript-шифрования на странице.
  • Бэкенд на браузерах, который выдерживает прод: пулы, жизненный цикл, восстановление после падений и порядок с процессами в контейнерах.
  • Долгие и сбойные бизнес-процессы, оформленные как устойчивые workflow с понятными финальными статусами.
  • Долгосрочное сопровождение боевой системы, пока платформа продолжает меняться; разборы инцидентов напрямую влияют на архитектуру.

Вопросы по кейсу

Зачем настоящие браузеры, если можно ходить в HTTP-эндпоинты платформы напрямую?

Платформа подписывает каждый запрос VM-обфусцированным JavaScript на странице и проверяет, что трафик похож на цельную браузерную сессию. Собственный код подписи платформы, запущенный в настоящей сессии Playwright, даёт корректные запросы без копирования чужой логики и продолжает работать, когда защиту пересобирают.

Что будет с заказом, если сессия на стороне платформы сломалась посередине?

Воркер классифицирует ответ. Если сессия больше не годится, он выводит её из оборота, освобождает маршрут, и Temporal повторяет заказ на свежем воркере в рамках бюджета времени. При окончательном отказе заказ сразу получает статус ошибки с понятной причиной и ссылкой на скриншот.

Как система масштабируется?

Каждый тип воркера — отдельный деплоймент в Kubernetes, который выполняет одну активность за раз на тёплом браузерном контексте. Пропускная способность растёт добавлением подов, а readiness-пробы шлюза уводят трафик с подов без готового контекста. Нагрузку и задержки проверяли в Locust.