RUEN
Обсудить проект

Инженерный кейс

Парк изолированных агентов

Панель управляет десятками учётных записей на торговой площадке. Каждая живёт на своём сервере, со своим адресом и своим устойчивым набором признаков браузера.

комбинаций признаков
7 200
бюджет перезапусков
5 / 300 с
сервер на запись
1

Панель и парк агентов: на каждую учётную запись — отдельный сервер со своим адресом, на нём работает агент, который держит соединение с площадкой и выполняет команды панели. Панель раздаёт задания, собирает состояние и показывает всё в одном окне.

Панель и агент живут на разных машинах — и протокол это признаёт

Описание протокола лежит двумя одинаковыми файлами — в панели и в агенте. Это не забытый дубль: компоненты разворачиваются на разных серверах и обновляются независимо, и общий пакет на двоих означал бы, что выкладка панели ломает агентов, до которых новый код ещё не доехал.

Поэтому в каждом сообщении авторизации едет номер версии протокола: стороны сразу понимают, совместимы ли они, вместо того чтобы выяснять это на первой непонятой команде.

Признаки выводятся из ключа записи, а не берутся случайно

Набор параметров браузера — строка агента, профиль подписи соединения, язык — выбирается детерминированно: хеш от ключа записи по модулю длины списка, для каждого параметра со своей солью. Один и тот же агент из раза в раз выглядит одинаково.

Очевидное решение — случайный набор при каждом запуске — выдало бы автоматизацию быстрее, чем его отсутствие: живой человек не меняет браузер и язык системы между заходами. В коде посчитан и запас: 30 × 20 × 12 ≈ 7 200 комбинаций, вероятность совпадения на двадцати записях около 2,7%.

Надзиратель перезапускает только то, что действительно упало

За фоновыми потоками агента следит собственный надзиратель. Его правило записано в коде вместе с причиной: перезапуск происходит только от пойманного исключения в самом потоке — и ни от чего другого.

До этого за живостью следил внешний сторож по косвенному признаку, и в один день он положил здоровых агентов, потому что признак оказался грубым. Бюджет перезапусков жёсткий — пять за триста секунд; исчерпался, значит поток останавливается насовсем и нужен разбор, а не бесконечная карусель.

Отдельно и намеренно не надзираются два цикла: слушатель площадки и переподключение к панели. У обоих своя логика восстановления, и двойной надзор гонялся бы с ней наперегонки.

Агент сам понимает, что его больше нет

Если панель двадцать раз подряд отвечает «такого токена не знаю» — а с нарастающей паузой это 15–25 минут, — агент считает, что запись удалили в базе, пока до сервера не доехало обновление. Он затирает свои доступы, помечает себя выведенным и выходит.

Без этого удалённая из панели запись продолжала бы стучаться и работать со своими доступами на сервере, про который все забыли.

Первая пауза короткая — из-за гонки с базой панели

Свежеразвёрнутый агент успевает попросить авторизацию раньше, чем панель дозапишет его в базу. Раньше повтор шёл через тридцать секунд, и старт превращался в минуты простоя на ровном месте. Теперь пауза начинается с трёх секунд и удваивается: гонка разрешается за один-два повтора, а редкая настоящая ошибка всё равно доходит до длинных пауз.

Python · asyncio · WebSocket · SQLite (WAL) · systemd · Caddy