250 lines
27 KiB
Markdown
250 lines
27 KiB
Markdown
# Стратегия Управления Прокси и Аккаунтами
|
||
|
||
В этом документе описывается интеллектуальная стратегия управления ресурсами (прокси и аккаунтами), используемая в `ytdlp-ops-server`. Цель этой системы — максимизировать процент успешных операций, минимизировать блокировки и обеспечить отказоустойчивость.
|
||
|
||
Сервер может работать в разных ролях для поддержки распределенной архитектуры, разделяя задачи управления и задачи генерации токенов.
|
||
|
||
---
|
||
|
||
## Роли Сервиса и Архитектура
|
||
|
||
Сервер предназначен для работы в одной из трех ролей, указываемых флагом `--service-role`:
|
||
|
||
- **`management`**: Один легковесный экземпляр сервиса, отвечающий за все вызовы API управления.
|
||
- **Назначение**: Предоставляет централизованную точку входа для мониторинга и управления состоянием всех прокси и аккаунтов в системе.
|
||
- **Поведение**: Предоставляет только функции управления (`getProxyStatus`, `banAccount` и т.д.). Вызовы функций генерации токенов будут завершаться ошибкой.
|
||
- **Развертывание**: Запускается как один контейнер (`ytdlp-ops-management`) и напрямую открывает свой порт на хост (например, порт `9091`), минуя Envoy.
|
||
|
||
- **`worker`**: Основная "рабочая лошадка" для генерации токенов и `info.json`.
|
||
- **Назначение**: Обрабатывает все запросы на генерацию токенов.
|
||
- **Поведение**: Реализует полный API, но его функции управления ограничены его собственным `server_identity`.
|
||
- **Развертывание**: Запускается как масштабируемый сервис (`ytdlp-ops-worker`) за балансировщиком нагрузки Envoy (например, порт `9080`).
|
||
|
||
- **`all-in-one`** (По умолчанию): Один экземпляр, который выполняет как управленческие, так и рабочие функции. Идеально подходит для локальной разработки или небольших развертываний.
|
||
|
||
Эта архитектура позволяет создать надежную, федеративную систему, где воркеры управляют своими ресурсами локально, в то время как центральный сервис предоставляет глобальное представление для управления и мониторинга.
|
||
|
||
---
|
||
|
||
## 1. Управление Жизненным Циклом Аккаунтов (Cooldown / Resting)
|
||
|
||
**Цель:** Предотвратить чрезмерное использование и последующую блокировку аккаунтов, предоставляя им периоды "отдыха" после интенсивной работы.
|
||
|
||
### Как это работает:
|
||
Жизненный цикл аккаунта состоит из трех состояний:
|
||
- **`ACTIVE`**: Аккаунт активен и используется для выполнения задач. При первом успешном использовании запускается таймер его активности.
|
||
- **`RESTING`**: Если аккаунт был в состоянии `ACTIVE` дольше установленного лимита, `AccountManager` автоматически переводит его в состояние "отдыха". В этом состоянии Airflow worker не будет выбирать его для новых задач.
|
||
- **Возврат в `ACTIVE`**: После завершения периода "отдыха" `AccountManager` автоматически возвращает аккаунт в состояние `ACTIVE`, делая его снова доступным.
|
||
|
||
### Конфигурация:
|
||
Эти параметры настраиваются при запуске `ytdlp-ops-server`.
|
||
|
||
- `--account-active-duration-min`: "Время работы" в **минутах**, которое аккаунт может быть непрерывно активным до перехода в `RESTING`.
|
||
- **Значение по умолчанию:** `30` (минут).
|
||
- `--account-cooldown-duration-min`: "Время отдыха" в **минутах**, которое аккаунт должен находиться в состоянии `RESTING`.
|
||
- **Значение по умолчанию:** `60` (минут).
|
||
|
||
**Где настраивать:**
|
||
Параметры передаются как аргументы командной строки при запуске сервера. При использовании Docker Compose это делается в файле `airflow/docker-compose-ytdlp-ops.yaml`:
|
||
```yaml
|
||
command:
|
||
# ... другие параметры
|
||
- "--account-active-duration-min"
|
||
- "${ACCOUNT_ACTIVE_DURATION_MIN:-30}"
|
||
- "--account-cooldown-duration-min"
|
||
- "${ACCOUNT_COOLDOWN_DURATION_MIN:-60}"
|
||
```
|
||
Вы можете изменить значения по умолчанию, установив переменные окружения `ACCOUNT_ACTIVE_DURATION_MIN` и `ACCOUNT_COOLDOWN_DURATION_MIN` в вашем `.env` файле.
|
||
|
||
**Соответствующие файлы:**
|
||
- `server_fix/account_manager.py`: Содержит основную логику для переключения состояний.
|
||
- `ytdlp_ops_server_fix.py`: Обрабатывает аргументы командной строки.
|
||
- `airflow/docker-compose-ytdlp-ops.yaml`: Передает аргументы в контейнер сервера.
|
||
|
||
---
|
||
|
||
## 2. Умная Стратегия Банов
|
||
|
||
**Цель:** Избежать необоснованных банов хороших прокси. Проблема часто может быть в аккаунте, а не в прокси, через который он работает.
|
||
|
||
### Как это работает:
|
||
|
||
#### Этап 1: Сначала Бан Аккаунта
|
||
- При возникновении серьезной ошибки, требующей бана (например, `BOT_DETECTED` или `SOCKS5_CONNECTION_FAILED`), система применяет санкции **только к аккаунту**, который вызвал ошибку.
|
||
- Для прокси эта ошибка просто фиксируется как один сбой, но сам прокси **не банится** и остается в работе.
|
||
|
||
#### Этап 2: Бан Прокси по "Скользящему Окну"
|
||
- Прокси блокируется автоматически, только если он демонстрирует **систематические сбои с РАЗНЫМИ аккаунтами** за короткий промежуток времени.
|
||
- Это является надежным индикатором того, что проблема именно в прокси. `ProxyManager` на сервере отслеживает это и автоматически банит такой прокси.
|
||
|
||
### Конфигурация:
|
||
Эти параметры **жестко заданы** как константы в коде и для их изменения требуется редактирование файла.
|
||
|
||
**Где настраивать:**
|
||
- **Файл:** `server_fix/proxy_manager.py`
|
||
- **Константы** в классе `ProxyManager`:
|
||
- `FAILURE_WINDOW_SECONDS`: Временное окно в секундах для анализа сбоев.
|
||
- **Значение по умолчанию:** `3600` (1 час).
|
||
- `FAILURE_THRESHOLD_COUNT`: Минимальное общее количество сбоев для запуска проверки.
|
||
- **Значение по умолчанию:** `3`.
|
||
- `FAILURE_THRESHOLD_UNIQUE_ACCOUNTS`: Минимальное количество **уникальных аккаунтов**, с которыми произошли сбои, чтобы забанить прокси.
|
||
- **Значение по умолчанию:** `3`.
|
||
|
||
**Соответствующие файлы:**
|
||
- `server_fix/proxy_manager.py`: Содержит логику "скользящего окна" и константы.
|
||
- `airflow/dags/ytdlp_ops_worker_per_url.py`: Функция `handle_bannable_error_callable` реализует политику бана "только аккаунт".
|
||
|
||
---
|
||
|
||
### Расшифровка Статусов Аккаунтов
|
||
|
||
Вы можете просмотреть статус всех аккаунтов с помощью DAG `ytdlp_mgmt_proxy_account`. Статусы имеют следующие значения:
|
||
|
||
- **`ACTIVE`**: Аккаунт исправен и доступен для использования. По умолчанию, аккаунт считается `ACTIVE`, если у него не установлен конкретный статус.
|
||
- **`BANNED`**: Аккаунт временно отключен из-за повторяющихся сбоев (например, ошибок `BOT_DETECTED`) или забанен вручную. В статусе будет указано время, оставшееся до его автоматического возвращения в `ACTIVE` (например, `BANNED (active in 55m)`).
|
||
- **`RESTING`**: Аккаунт использовался в течение длительного времени и находится в обязательном периоде "отдыха" для предотвращения "выгорания". В статусе будет указано время, оставшееся до его возвращения в `ACTIVE` (например, `RESTING (active in 25m)`).
|
||
- **(Пустой Статус)**: В более старых версиях аккаунт, у которого были только сбои (и ни одного успеха), мог отображаться с пустым статусом. Это было исправлено; теперь такие аккаунты корректно отображаются как `ACTIVE`.
|
||
|
||
---
|
||
|
||
## 3. Сквозной Процесс Ротации: Как Всё Работает Вместе
|
||
|
||
Этот раздел описывает пошаговый процесс того, как воркер получает аккаунт и прокси для одной задачи, объединяя все вышеописанные стратегии управления.
|
||
|
||
1. **Инициализация Воркера (`ytdlp_ops_worker_per_url`)**
|
||
- Запускается DAG, инициированный либо оркестратором, либо предыдущим успешным запуском самого себя.
|
||
- Задача `pull_url_from_redis` извлекает URL из очереди `_inbox` в Redis.
|
||
|
||
2. **Выбор Аккаунта (Воркер Airflow)**
|
||
- Выполняется задача `assign_account`.
|
||
- Она генерирует полный список потенциальных ID аккаунтов на основе параметра `account_pool` (например, от `my_prefix_01` до `my_prefix_50`).
|
||
- Она подключается к Redis и проверяет статус каждого аккаунта из этого списка.
|
||
- Она создает новый временный список, содержащий только те аккаунты, которые **не** находятся в состоянии `BANNED` или `RESTING`.
|
||
- Если итоговый список активных аккаунтов пуст, воркер завершается с ошибкой (если не включено автосоздание).
|
||
- Затем из отфильтрованного списка активных аккаунтов с помощью **`random.choice()`** выбирается один.
|
||
- Выбранный `account_id` передается следующей задаче.
|
||
|
||
3. **Выбор Прокси (`ytdlp-ops-server`)**
|
||
- Выполняется задача `get_token`, которая отправляет случайно выбранный `account_id` в Thrift RPC-вызове на `ytdlp-ops-server`.
|
||
- На сервере у `ProxyManager` запрашивается прокси.
|
||
- `ProxyManager`:
|
||
a. Обновляет свое внутреннее состояние, загружая статусы всех прокси из Redis.
|
||
b. Фильтрует список, оставляя только прокси со статусом `ACTIVE`.
|
||
c. Применяет политику бана по "скользящему окну", потенциально блокируя прокси, которые недавно слишком часто выходили из строя.
|
||
d. Выбирает следующий доступный прокси из активного списка, используя индекс **round-robin** (по кругу).
|
||
e. Возвращает выбранный `proxy_url`.
|
||
|
||
4. **Выполнение и Отчетность**
|
||
- Теперь у сервера есть и `account_id` (от Airflow), и `proxy_url` (от его `ProxyManager`).
|
||
- Он приступает к процессу генерации токенов, используя эти ресурсы.
|
||
- По завершении (успешном или неудачном) он сообщает о результате в Redis, обновляя статусы для конкретного аккаунта и прокси, которые были использованы. Это влияет на их счетчики сбоев, таймеры "отдыха" и т.д. для следующего запуска.
|
||
|
||
Это разделение ответственности является ключевым:
|
||
- **Воркер Airflow (задача `assign_account`)** отвечает за **случайный выбор активного аккаунта**, сохраняя при этом "привязку" (повторно используя тот же аккаунт после успеха).
|
||
- **Сервер `ytdlp-ops-server`** отвечает за **циклический выбор (round-robin) активного прокси**.
|
||
|
||
---
|
||
|
||
## 4. Автоматический Бан Аккаунтов по Количеству Сбоев
|
||
|
||
**Цель:** Автоматически выводить из ротации аккаунты, которые постоянно вызывают ошибки, не связанные с баном (например, неверный пароль, проблемы с авторизацией).
|
||
|
||
### Как это работает:
|
||
- `AccountManager` отслеживает количество **последовательных** сбоев для каждого аккаунта.
|
||
- При успешной операции счетчик сбрасывается.
|
||
- Если количество последовательных сбоев достигает заданного порога, аккаунт автоматически банится на определенный срок.
|
||
|
||
### Конфигурация:
|
||
Эти параметры задаются в конструкторе класса `AccountManager`.
|
||
|
||
**Где настраивать:**
|
||
- **Файл:** `server_fix/account_manager.py`
|
||
- **Параметры** в `__init__` метода `AccountManager`:
|
||
- `failure_threshold`: Количество последовательных сбоев до бана.
|
||
- **Значение по умолчанию:** `5`.
|
||
- `ban_duration_s`: Длительность бана в секундах.
|
||
- **Значение по умолчанию:** `3600` (1 час).
|
||
|
||
---
|
||
|
||
## 5. Мониторинг и Восстановление
|
||
|
||
### Как Проверить Статусы
|
||
DAG **`ytdlp_mgmt_proxy_account`** — это основной инструмент для мониторинга состояния ваших ресурсов. Он подключается напрямую к **сервису управления** для выполнения действий.
|
||
|
||
- **ID DAG'а:** `ytdlp_mgmt_proxy_account`
|
||
- **Как использовать:** Запустите DAG из интерфейса Airflow. Убедитесь, что параметры `management_host` и `management_port` правильно указывают на ваш экземпляр сервиса `ytdlp-ops-management`. Для получения полного обзора установите параметры:
|
||
- `entity`: `all`
|
||
- `action`: `list`
|
||
- **Результат:** В логе DAG'а будут отображены таблицы с текущим статусом всех аккаунтов и прокси. Для аккаунтов в состоянии `BANNED` или `RESTING` будет показано время, оставшееся до их активации (например, `RESTING (active in 45m)`). Для прокси будет подсвечено, какой из них является следующим `(next)` в ротации для конкретного воркера.
|
||
|
||
### Что Произойдет, если Все Аккаунты Будут Забанены или в "Отдыхе"?
|
||
Если весь пул аккаунтов станет недоступен (в статусе `BANNED` или `RESTING`), система по умолчанию приостановит работу.
|
||
- DAG `ytdlp_ops_worker_per_url` завершится с ошибкой `AirflowException` на шаге `assign_account`, так как пул активных аккаунтов будет пуст.
|
||
- Это остановит циклы обработки. Система будет находиться в состоянии паузы до тех пор, пока аккаунты не будут разбанены вручную или пока не истечет их таймер бана/отдыха. После этого вы сможете перезапустить циклы обработки с помощью DAG'а `ytdlp_ops_orchestrator`.
|
||
- Граф выполнения DAG `ytdlp_ops_worker_per_url` теперь явно показывает такие задачи, как `assign_account`, `get_token`, `ban_account`, `retry_get_token` и т.д., что делает поток выполнения и точки сбоя более наглядными.
|
||
|
||
Систему можно настроить на автоматическое создание новых аккаунтов, чтобы предотвратить полную остановку обработки.
|
||
|
||
#### Автоматическое Создание Аккаунтов при Исчерпании
|
||
- **Цель**: Обеспечить непрерывную работу конвейера обработки, даже если все аккаунты в основном пуле временно забанены или находятся в "отдыхе".
|
||
- **Как это работает**: Если параметр `auto_create_new_accounts_on_exhaustion` установлен в `True` и пул аккаунтов задан с помощью префикса (а не явного списка), система сгенерирует новый уникальный ID аккаунта, когда обнаружит, что активный пул пуст.
|
||
- **Именование новых аккаунтов**: Новые аккаунты создаются в формате `{prefix}-auto-{уникальный_id}`.
|
||
- **Конфигурация**:
|
||
- **Параметр**: `auto_create_new_accounts_on_exhaustion`
|
||
- **Где настраивать**: В конфигурации DAG `ytdlp_ops_orchestrator` при запуске.
|
||
- **Значение по умолчанию**: `True`.
|
||
|
||
---
|
||
|
||
## 6. Обработка Сбоев и Политика Повторных Попыток
|
||
|
||
**Цель:** Обеспечить гибкое управление поведением системы, когда воркер сталкивается с ошибкой, требующей бана (например, `BOT_DETECTED`).
|
||
|
||
### Как это работает
|
||
Когда задача `get_token` воркера завершается с ошибкой, требующей бана, поведение системы определяется политикой `on_bannable_failure`, которую можно настроить при запуске `ytdlp_ops_orchestrator`.
|
||
|
||
### Конфигурация
|
||
- **Параметр**: `on_bannable_failure`
|
||
- **Где настраивать**: В конфигурации DAG `ytdlp_ops_orchestrator`.
|
||
- **Опции**:
|
||
- `stop_loop` (Самая строгая):
|
||
- Использованный аккаунт банится.
|
||
- URL помечается как сбойный в хэше `_fail` в Redis.
|
||
- Цикл обработки воркера **останавливается**. "Линия" обработки становится неактивной.
|
||
- `retry_with_new_account` (По умолчанию, самая отказоустойчивая):
|
||
- Аккаунт, вызвавший сбой, банится.
|
||
- Воркер немедленно повторяет обработку **того же URL** с новым, неиспользованным аккаунтом из пула.
|
||
- Если повторная попытка успешна, воркер продолжает свой цикл для обработки следующего URL.
|
||
- Если повторная попытка также завершается сбоем, второй аккаунт **и использованный прокси** также банятся, и цикл работы воркера останавливается.
|
||
- `retry_and_ban_account_only`:
|
||
- Похожа на `retry_with_new_account`, но при втором сбое банится **только второй аккаунт**, а не прокси.
|
||
- Это полезно, когда вы доверяете своим прокси, но хотите агрессивно перебирать сбойные аккаунты.
|
||
- `retry_without_ban` (Самая мягкая):
|
||
- Воркер повторяет попытку с новым аккаунтом, но **ни аккаунты, ни прокси никогда не банятся**.
|
||
- Эта политика полезна для отладки или когда вы уверены, что сбои являются временными и не вызваны проблемами с ресурсами.
|
||
|
||
Эта политика позволяет системе быть устойчивой к сбоям отдельных аккаунтов, не теряя URL, и в то же время обеспечивает гранулярный контроль над тем, когда банить аккаунты и/или прокси, если проблема сохраняется.
|
||
|
||
---
|
||
|
||
## 7. Логика Работы Worker DAG (`ytdlp_ops_worker_per_url`)
|
||
|
||
Этот DAG является "рабочей лошадкой" системы. Он спроектирован как самоподдерживающийся цикл для обработки одного URL за запуск. Логика обработки сбоев и повторных попыток теперь явно видна в графе задач DAG.
|
||
|
||
### Задачи и их назначение:
|
||
|
||
- **`pull_url_from_redis`**: Извлекает один URL из очереди `_inbox` в Redis. Если очередь пуста, DAG завершается со статусом `skipped`, останавливая эту "линию" обработки.
|
||
- **`assign_account`**: Выбирает аккаунт для задачи. Он поддерживает **привязку аккаунта (affinity)**, повторно используя тот же аккаунт из предыдущего успешного запуска в своей "линии". Если это первый запуск или предыдущий был неудачным, он выбирает случайный активный аккаунт.
|
||
- **`get_token`**: Основная попытка получить токены и `info.json` путем вызова `ytdlp-ops-server`.
|
||
- **`handle_bannable_error_branch`**: Задача-развилка, которая запускается в случае сбоя `get_token`. Она анализирует ошибку и определяет следующий шаг на основе политики `on_bannable_failure`.
|
||
- **`ban_account_and_prepare_for_retry`**: Если разрешен повтор, эта задача банит сбойный аккаунт и выбирает новый.
|
||
- **`retry_get_token`**: Вторая попытка получить токен с использованием нового аккаунта.
|
||
- **`ban_second_account_and_proxy`**: Если и повторная попытка завершается неудачей, эта задача банит второй аккаунт и использованный прокси.
|
||
- **`download_and_probe`**: Если `get_token` или `retry_get_token` завершается успешно, эта задача использует `yt-dlp` для скачивания медиа и `ffmpeg` для проверки целостности файла.
|
||
- **`mark_url_as_success`**: Если `download_and_probe` завершается успешно, эта задача записывает успешный результат в хэш `_result` в Redis.
|
||
- **`handle_generic_failure`**: Если любая задача завершается с неисправимой ошибкой, эта задача записывает подробную информацию об ошибке в хэш `_fail` в Redis.
|
||
- **`decide_what_to_do_next`**: Финальная задача-развилка, которая решает, продолжать ли цикл (`trigger_self_run`), остановить его корректно (`stop_loop`) или пометить как сбойный (`fail_loop`).
|
||
- **`trigger_self_run`**: Задача, которая фактически запускает следующий экземпляр DAG, создавая непрерывный цикл.
|
||
|