243 lines
22 KiB
Plaintext
243 lines
22 KiB
Plaintext
RFB — обновление для 11 независимых серверов
|
||
Версия: 2.1.1
|
||
Дата: 11.10.2026
|
||
|
||
Каждая машина сама обслуживает домашний матч своей команды (--team).
|
||
Центральный сборщик не требуется. Существующие 25 маршрутов и структуры
|
||
успешных ответов для vMix сохранены. Добавлены отдельные маршруты
|
||
/api_health, /logs, /logs/data и POST /logs/telegram-test.
|
||
|
||
ИСПРАВЛЕНИЕ ПРОПАДАНИЯ ДАННЫХ В ONLINE
|
||
|
||
В версии 2.1.0 очередной ответ game заменял собранный live-объект:
|
||
составы, статистика и события могли исчезать до следующего box-score/PBP.
|
||
Дополнительно пустой PBP очищал события, а частичная статистика без
|
||
isStart/points могла приводить к HTTP 500 на /team_stats.
|
||
|
||
Теперь game, последний принятый box-score и PBP собираются в отдельном
|
||
объекте. После проверки он публикуется одной заменой. Уже опубликованные
|
||
данные при сборке не меняются. Обновление game сохраняет известные поля
|
||
при пустых составах, отсутствующих полях и null; live-статистика и события
|
||
накладываются из последних принятых ответов для ТОГО ЖЕ матча. Частичный
|
||
box-score дополняет статистику, сохраняя известные флаги и остальные поля.
|
||
Новые числовые нули и false применяются как обычные исправления.
|
||
|
||
Пустой PBP при live/завершении матча с уже загруженными событиями
|
||
отклоняется. До первого события пустой список допустим. Непустой PBP
|
||
заменяет предыдущий: реальные исправления/удаления событий применяются.
|
||
Числовое время броска 0 больше не вызывает ошибку преобразования.
|
||
Неполный первый game нового матча оставляет последний готовый JSON до
|
||
получения полного состава. Статистика предыдущего матча не переносится
|
||
в новый. Поздние ответы чужого матча/поколения потоков отбрасываются.
|
||
|
||
Последние принятые box-score/PBP сохраняются в локальном снимке вместе
|
||
с собранным game. Снимки 2.1.0 читаются с восстановлением live-источников
|
||
из готового game. На /logs добавлены «Публикация JSON» и состояние
|
||
«Сохранены данные»: видно, когда ответ не принят, почему и насколько
|
||
стары данные для эфира. HTTP 200 неполного ответа не обновляет их возраст.
|
||
В /api_health добавлен блок publication. Форматы существующих выходов
|
||
и периодичность API-запросов сохранены; дополнительных запросов нет.
|
||
|
||
УСТАНОВКА НА СУЩЕСТВУЮЩИЙ СЕРВЕР
|
||
|
||
1. Уточните рабочую папку:
|
||
systemctl show rfb-data.service -p WorkingDirectory
|
||
|
||
2. Загрузите ZIP на машину через VS Code/SFTP. Распакуйте в ОТДЕЛЬНУЮ
|
||
папку. Для проекта в /root/RFB выполните:
|
||
unzip rfb_independent_servers_optimized.zip -d /tmp/rfb-update-2.1.1
|
||
sudo bash /tmp/rfb-update-2.1.1/update.sh /root/RFB
|
||
|
||
Вместо /root/RFB укажите фактический WorkingDirectory.
|
||
Для проверки архива без установки:
|
||
bash /tmp/rfb-update-2.1.1/update.sh /root/RFB --check
|
||
|
||
Установка кратковременно перезапускает сервис: выполняйте её вне эфира.
|
||
|
||
3. Проверьте результат:
|
||
systemctl status rfb-data.service --no-pager
|
||
curl -s http://127.0.0.1:8000/api_health
|
||
Откройте http://АДРЕС_МАШИНЫ:8000/logs
|
||
|
||
update.sh проверяет контрольные суммы и синтаксис, сохраняет резервную
|
||
копию файлов рядом с проектом, останавливает сервис, устанавливает код,
|
||
отмечает точное время установки, добавляет systemd drop-in и запускает
|
||
сервис. Затем проверяет локальный /api_health и версию. Доступность API
|
||
RFB и Telegram для этой проверки не требуется. Если установка после
|
||
остановки не завершилась, скрипт восстанавливает файлы и прежний drop-in;
|
||
сервис запускается вновь, если был активен до обновления. Новые файлы,
|
||
которых не было в старой версии, при откате перемещаются в failed-update
|
||
внутри резервной копии. Старый .env, виртуальное окружение, --team,
|
||
--league, --lang и ExecStart сервиса сохраняются. Скрипт требует доступа
|
||
к systemctl и записи в рабочую папку; обычный запуск — через sudo.
|
||
|
||
Новые параметры конфигурации дополняют polling_config.json. Имеющиеся
|
||
значения сохраняются; прежний стандарт prepare_minutes=70 заменяется
|
||
на 90. Свои другие интервалы и лимит проверьте после установки.
|
||
Новые зависимости Python не нужны; используйте рабочее окружение проекта.
|
||
Запускайте один процесс сборщика на машину, без нескольких uvicorn workers.
|
||
|
||
Архив содержит 9 файлов: get_data.py, rfb_polling.py, rfb_runtime.py,
|
||
rfb_logs.html, rfb_version.json, polling_config.json, update.sh, deploy.sh,
|
||
README_RU.txt. .env, requirements.txt, ваши данные и исходные логи в архив
|
||
не включены. Для этого обновления deploy.sh запускать НЕ требуется:
|
||
его загрузка Git-ветки может вернуть старый код. Для будущего deploy.sh
|
||
добавьте новые файлы в используемую ветку/релиз проекта.
|
||
|
||
МОНИТОРИНГ /logs
|
||
|
||
Страница работает в самом FastAPI без отдельного сервера и внешних CDN.
|
||
Она показывает:
|
||
- версию сборки, дату сборки, установку, запуск процесса и время работы;
|
||
- режим: ожидание, подготовка, live, завершение;
|
||
- API-запросы и входящие HTTP-запросы отдельно, за последние 60 секунд;
|
||
- лимит машины и оставшуюся паузу после запрета/ограничения/сетевого сбоя;
|
||
- состояние каждого источника, возраст последних принятых данных,
|
||
HTTP-код, длительность ответа и время до следующей попытки;
|
||
- CPU процесса (в процентах одного ядра), RAM процесса и свободную RAM VM;
|
||
- графики API, входящих запросов и CPU за последние 15 минут;
|
||
- долю ответов из кэша, HTTP 503/500, состояния Excel/NAS и Telegram;
|
||
- журнал последних 400 событий с поиском, фильтром и скачиванием.
|
||
|
||
Графики и счётчики начинаются заново при перезапуске процесса. В журнал
|
||
поднимается ограниченный хвост локального лог-файла, поэтому видны и
|
||
недавние события прошлого запуска. Скачивание на странице сохраняет
|
||
события из её текущего буфера, а не весь суточный журнал. Полный журнал:
|
||
journalctl -u rfb-data.service --since today --no-pager > rfb-day.log
|
||
|
||
Мониторинг НЕ опрашивает RFB: использует уже имеющиеся данные процесса.
|
||
Обновление страницы — каждые 5 секунд; скрытая вкладка прекращает опрос.
|
||
Длинные сообщения ограничены, токены/пароли скрываются, текст HTML
|
||
экранируется. Журнал не превращается в список каждого запроса vMix.
|
||
503 на выходе до готовности данных — ожидание прогрева, 500 — ошибка.
|
||
DNS/сеть, HTTP 429, HTTP 401/403 и ошибки приложения показываются отдельно.
|
||
Если сам сервис остановлен, открытая страница перестанет обновляться:
|
||
она покажет отсутствие связи. Полностью остановленный сервис не может
|
||
отдать новую HTML-страницу; тогда проверяйте systemctl/journalctl.
|
||
|
||
update.sh сохраняет дату установки в .rfb_deployment.json. При ручном
|
||
копировании без скрипта страница честно показывает время обнаружения
|
||
нового кода при запуске. Чтобы отметить установку вручную, после копирования:
|
||
cd /root/RFB
|
||
.venv/bin/python rfb_runtime.py --mark-deployed /root/RFB
|
||
systemctl restart rfb-data.service
|
||
|
||
По желанию добавьте в .env защиту только страницы диагностики:
|
||
RFB_LOGS_USER=rfb
|
||
RFB_LOGS_PASSWORD=ваш_пароль
|
||
Затем перезапустите сервис. Браузер запросит логин и пароль. Выходы vMix
|
||
и существующие маршруты остаются доступны по прежним адресам.
|
||
|
||
TELEGRAM
|
||
|
||
Используются уже существующие параметры .env:
|
||
TELEGRAM_TOKEN=токен_вашего_бота
|
||
TELEGRAM_CHAT_ID=идентификатор_чата
|
||
|
||
Отправка вынесена в отдельный поток: очередь ограничена 128 сообщениями,
|
||
проблема Telegram больше не задерживает сбор API и выдачу данных.
|
||
INFO, предупреждения и ошибки поступают в очередь; сводка нагрузки
|
||
[metrics] не отправляется. Одинаковые предупреждения подавляются на
|
||
5 минут. Сводка live остаётся примерно раз в 5 минут. При 429 учитывается
|
||
retry_after; при неверном токене/чате или запрете — пауза 10 минут;
|
||
при сетевой ошибке паузы растут. До 3 попыток на сообщение; сообщения
|
||
старше 30 минут и переполнение очереди учитываются как отброшенные.
|
||
Очередь сообщений не сохраняется после остановки процесса.
|
||
|
||
Нажмите «Проверить доставку» на /logs. «Добавлен в очередь» означает
|
||
только постановку в очередь: успешная доставка подтверждается счётчиком
|
||
и временем последней доставки в блоке Telegram. Тест ограничен одним
|
||
запросом в минуту. При отказе отображается причина без токена.
|
||
Если токен/чат не заданы, Telegram отключён и остальная система работает.
|
||
Сеть до api.telegram.org, доступ бота к чату и реальные учётные данные
|
||
нужно проверить на каждой VM: локальные проверки использовали имитацию.
|
||
|
||
РЕЖИМЫ И НАГРУЗКА API
|
||
|
||
Без домашнего матча сегодня и до T−90 минут — ожидание: календарь
|
||
примерно раз в 15 минут, сезоны раз в сутки. Статистика старого матча
|
||
не запрашивается, последние исправные данные доступны из кэша.
|
||
Это около 4 календарных запросов в час на машину, около 44 на все 11
|
||
ожидающих машин, плюс запуск, сезоны и повторы после ошибок.
|
||
|
||
T−90 минут — подготовка: составы, метаданные, общая статистика;
|
||
live-status раз в 30 секунд, последние 5 минут перед стартом — раз в 10.
|
||
Если старт уже известен из календаря, переход планируется к T−90 и
|
||
не задерживается ещё на 15 минут до следующего календарного опроса.
|
||
Само наступление времени старта не включает частый live без Online/Live.
|
||
|
||
Live: live-status примерно раз в секунду, box-score и play-by-play
|
||
раз в 5 секунд. Метаданные и таблица — раз в 5 минут. Сезонная и общая
|
||
статистика — однократно после успеха, с повтором при ошибках. Полные
|
||
pregame прекращают опрашиваться после получения готовых данных в live.
|
||
Другие матчи опрашиваются только при недавнем использовании /games_online
|
||
и собственном активном матче; не чаще раз в 30 секунд на чужой матч.
|
||
|
||
После завершения — финальное обновление, до 3 попыток на одноразовый
|
||
источник, затем ожидание через 10 минут. Возобновление игры возвращает
|
||
live. Ночной матч продолжает обновляться после полуночи.
|
||
|
||
Два изолированных HTTP-транспорта обслуживают оперативные источники и
|
||
тяжёлую статистику, при этом бюджет у них ОДИН на весь процесс.
|
||
Тяжёлые ответы не блокируют оперативный Session. Для тяжёлой статистики
|
||
read timeout 15 секунд; повтор 60, 120, 240 секунд и далее до 15 минут.
|
||
После двух сетевых/DNS-сбоев включается общая пауза по хосту с одной
|
||
пробной попыткой; паузы растут до 5 минут. Это уменьшает число попыток,
|
||
но не исправляет DNS, маршрутизацию или недоступность удалённого сервера.
|
||
|
||
429 — общая пауза минимум 120 секунд с учётом Retry-After; 401/403 —
|
||
минимум 600 секунд. Ограничение по времени сохраняется в снимке на диск,
|
||
включая корректное завершение сервиса. Сбой/невалидный JSON/неполные
|
||
данные не заменяют последнее исправное значение. Поздние ответы старой
|
||
группы потоков и чужого матча отбрасываются.
|
||
|
||
По умолчанию max_requests_per_minute=90 НА ОДНУ машину. Это настройка
|
||
пакета, не подтверждённая квота RFB. Если квота общая по ключу/IP,
|
||
индивидуальные лимиты надо распределить так, чтобы их сумма укладывалась
|
||
в неё: 11 одновременно активных машин по 90 дают максимум 990/мин.
|
||
Без точной квоты гарантировать отсутствие блокировок нельзя. Пустые VM
|
||
до этого максимума не доходят. Периоды — целевые: ответы API, лимит,
|
||
случайный разнос запуска и повторные попытки увеличивают задержку.
|
||
Меньший лимит уменьшит нагрузку ценой более редких live-обновлений.
|
||
|
||
ОПТИМИЗАЦИЯ VM И СОВМЕСТИМОСТЬ
|
||
|
||
- Частые выходы кэшируют уже сериализованный ответ по версиям входных
|
||
данных и параметрам запроса. При новом счёте/событиях/Excel кэш меняется.
|
||
- /status копирует только нужные поля вместо всей большой статистики.
|
||
- HTTP access log отключён; остаются ошибки, агрегированные счётчики и
|
||
сводка нагрузки раз в 5 минут. Файлы INFO/WARNING/ERROR: до 5 × 5 МБ.
|
||
- Снимок кэша копируется и записывается только при изменении данных.
|
||
В ожидании нет постоянных одинаковых больших записей на диск.
|
||
- Excel/NAS читаются раз в 15 минут в ожидании и раз в минуту в активном
|
||
режиме. Переход к подготовке сразу будит Excel-поток.
|
||
- Иконки карт бросков кэшируются на диске; после рестарта используются
|
||
до обращения к NAS. Первая отрисовка даёт загрузке иконок до 15 секунд.
|
||
При недоступности NAS работают круги; появление иконок обновляет карты.
|
||
- Карты бросков строятся при изменении бросков/ресурсов; PNG-кэш ограничен.
|
||
- /commentary использует один цикл опроса, ждёт завершения предыдущего,
|
||
реже обновляет страницу вне live и не опрашивает из скрытой вкладки.
|
||
- Автоперезагрузка Uvicorn выключена. systemd ждёт network-online.target
|
||
и ограничивает циклы неудачного старта, не меняя расписание перезагрузок VM.
|
||
|
||
Рабочий каталог кэша — .rfb_cache. Для него,
|
||
logs и .rfb_deployment.json сервису нужен доступ на запись. Кэш должен
|
||
оставаться локальным и отдельным у каждого сервера/команды.
|
||
|
||
ПРОВЕРКИ
|
||
|
||
Сравнивались старые 25 выходов и новый код: JSON-поля, типы, сортировка,
|
||
HTML/JSON /status, заголовки и PNG. Проверены настоящие HTTP-обработчики
|
||
FastAPI с подставными ответами внешних сервисов, обновление кэша после
|
||
счёта и PBP, ожидание/подготовка/полуночный матч, ошибки 429/DNS,
|
||
тяжёлая статистика, Telegram, логирование, сохранение снимков и метаданные.
|
||
Проверены JavaScript страницы, экранирование и смена сессии после рестарта,
|
||
синтаксис Python и shell, установка/откат в изолированных тестовых папках.
|
||
Для 2.1.1 воспроизведены четыре сценария очистки данных на старом коде.
|
||
Проверены чтение во время публикации, частичные/пустые/невалидные ответы,
|
||
сохранение нулей/false, смена матча, рестарт, миграция кэша 2.1.0,
|
||
обновление настоящего счёта/событий и диагностика отклонённых обновлений.
|
||
Реальный API RFB, реальные Telegram-реквизиты и загрузка vMix на ваших
|
||
серверах здесь не запускались. После установки на первой VM проверьте
|
||
реальный матч и данные vMix; затем поставьте архив на остальные с их --team.
|