Files
hockey_new/README_BUILD172_RU.md
2026-09-29 13:51:57 +03:00

18 KiB
Raw Permalink Blame History

Build172 — ночное обновление КХЛ, отчёт и повтор неудачных записей

Версия приложения: 2026.09.29.9. Основа: build171 (2026.09.29.8).

Установка

В архиве только 5 рабочих файлов и эта инструкция. Остановите приложение, скопируйте файлы с сохранением структуры папок, затем запустите приложение и обновите браузер через Ctrl+F5:

  • app.py
  • khl_site/khl_data_center.py
  • khl_site/khl_site_collector.py
  • khl_site/update_runtime.py — новый обязательный модуль
  • khl_site/web/index.html

Для стандартного Linux-развёртывания имя службы — khl-data.service. После замены файлов: sudo systemctl restart khl-data.service. Если служба называется иначе, используйте её имя.

Рабочие настройки, базы данных, .env и сохранённые архивы КХЛ в пакет не включены. Файлы данных на сервере заменять не требуется.

Что изменено

  1. Загрузчик КХЛ по умолчанию работает одним потоком вместо трёх. Перед сетевыми запросами используется пауза 0,5 секунды. Эти значения применяются и к ручным обновлениям в веб-интерфейсе.
  2. Полное обновление игроков, тренеров и судей автоматически запускается ежедневно в 03:00 по Москве. Браузер открывать не нужно; сервер приложения должен работать.
  3. Дата автоматического запуска сохраняется перед стартом. В тот же день он не запускается снова после ошибки или перезапуска сервера. Ручной запуск и ночное обновление защищены от одновременного выполнения общей блокировкой.
  4. Во вкладке «КХЛ сайт» появилась кнопка «Отчёт обновлений»: время, длительность, результат по разделам, число полученных карточек, проблемы, состояние импорта в БД и следующая дата запуска. Отчёт можно скачать. Смотреть его могут операторы; запуск обновлений сохраняет прежнее ограничение для администраторов.
  5. Ошибки сохраняются с разделом и ID. Кнопка «Повторить неудачные» загружает только карточки из очереди. Уже успешно записанные карточки пропускаются. Если не удалось прочитать список участников, список перечитывается, после чего из него исключаются ранее успешно загруженные карточки.
  6. Ошибка сети или разбора карточки сохраняет её прежние данные. Если статистику не удалось разобрать целиком, используется предусмотренное сохранение прежней статистики, а карточка остаётся в очереди повтора. Успех удаляется из очереди только после записи файла данных. При полном отказе загрузки прежний архив не перезаписывается.
  7. Если файлы загрузились, но импорт в БД завершился ошибкой, кнопка повтора может повторить только импорт сохранённых файлов, без обращения к КХЛ.
  8. Отчёт, очередь ошибок и отметка ночного запуска сохраняются после перезапуска. В отчёте показываются первые 50 ошибок; скачиваемый файл содержит полную очередь.

Повтор — ручной, через кнопку в отчёте. Бесконечного автоматического повтора при недоступности КХЛ нет. Следующее плановое обновление — следующей ночью.

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

Настройки и расписание

При первом запуске автоматически создаётся файл settings/local/khl_updates.json, если его ещё нет:

{
  "enabled": true,
  "time": "03:00",
  "workers": 1,
  "request_delay_seconds": 0.5,
  "window_minutes": 60
}

Время всегда московское (Europe/Moscow), независимо от часового пояса ОС. Планировщик проверяет время каждые 30 секунд. При перезапуске между 03:00 и 03:59 пропущенный запуск может начаться в этом окне, если сегодня ещё не запускался. Если сервер всё это окно был выключен, днём загрузка не стартует: следующий запуск — следующей ночью. Если другое обновление занимает всё окно, ночной запуск пропускается.

Настройки перечитываются без перезапуска; изменение числа потоков и задержки применяется к следующей загрузке. Для снижения нагрузки оставьте workers=1. Выключение автоматического запуска: enabled=false. Уже выполняющийся сбор это не прерывает.

Создаваемые рабочие файлы:

  • settings/local/khl_update_state.json — последний запуск, отчёт, импорт и дата ночного запуска;
  • settings/local/khl_update_state.lock — блокировка выполняющегося задания;
  • khl_site/data/khl_update_pending.json — очередь неудачных/незавершённых записей;
  • khl_site/data/khl_update_report.json — диагностика последнего запуска загрузчика;
  • прежние khl_site/data/khl_*_all.json — сами данные.

Эти файлы создаются приложением и не входят в обновление. Каталоги settings/local и khl_site/data должны быть доступны для записи пользователю службы. Очередь умеет восстановить ошибки из архивов предыдущей версии, если отдельного файла очереди ещё нет.

Результаты проверки CPU

Аудит проведён по исходному коду build171/172. Доступа к метрикам действующего сервера не было; причина конкретного сигнала «100% CPU» на сервере пока не подтверждена.

Подтверждён существенный источник лишней работы в hockey_data/service.py: при изменении JSON онлайн-матча sync_live_game() вызывает sync_match_details(), который повторно разбирает справочники и сохраняет профили всего турнира. Кэш справочника хранит ответ источника, но не исключает повторный разбор и запись. Даже неизменившимся профилям обновляется время синхронизации. Полная карточка матча также собирается до и после обновления. В этой версии данный участок Stat2TV не оптимизирован.

Изолированный замер реального метода сохранения справочника, синтетические профили, локальная SQLite, три повторных сохранения неизменившихся данных:

Профилей SQL-вызовов за повтор Из них SELECT / UPDATE Медиана CPU-времени процесса
100 600 300 / 300 0,095 с
500 3 000 1 500 / 1 500 0,537 с
1 000 6 000 3 000 / 3 000 0,911 с

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

Дополнительные источники нагрузки:

  • через 15 секунд после старта сервера начинается фоновая синхронизация расписаний; далее она выполняется примерно раз в час;
  • автообновление Mapping повторяет SQL-источники; отправка только изменившихся значений в vMix не отменяет сами SQL-запросы;
  • клиент Stat2TV создаёт новый HTTP-клиент на каждый запрос, без повторного использования соединения между вызовами;
  • полный сбор КХЛ и последующий импорт больших архивов в БД могут давать пики. В build172 сбор перенесён на ночь и уменьшен до одного потока, но один поток тоже способен занять одно ядро на обработке данных.

Следующие приоритетные оптимизации Stat2TV: не перезаписывать неизменившийся справочник, объединить одновременные обновления одного матча, повторно использовать HTTP-соединения. Добавление RAM или ядер само по себе не устраняет эти причины.

Ориентир по серверу

Ниже инженерная оценка для планирования, а не гарантированные минимальные требования. Точный размер зависит от числа открытых матчей/браузеров, объёма архивов, SQL Mapping и размещения БД. vMix и обработка видео в эти цифры не входят.

Размещение CPU Оперативная память Диск
Тестовый стенд, PostgreSQL отдельно 2 vCPU 4 ГБ SSD от 40 ГБ
Рабочий веб-сервер, PostgreSQL отдельно 4 vCPU с гарантированным ресурсом 8 ГБ SSD/NVMe 60–80 ГБ
Приложение и PostgreSQL на одном сервере 6–8 vCPU 16 ГБ SSD/NVMe 100–150 ГБ

Для начала я бы выбрал 4 vCPU / 8 ГБ RAM при отдельной БД либо 8 vCPU / 16 ГБ RAM при совместном размещении. Для большого числа матчей и операторов сначала нужен замер после оптимизации указанного участка, затем масштабирование.

ОС: 64-битный Linux. Python 3.12 подходит для проверенного окружения; зависимости устанавливаются из requirements.txt. База — PostgreSQL. GPU веб-приложению не требуется. Нужен стабильный интернет для КХЛ/Stat2TV; при отдельной БД важна небольшая задержка между приложением и БД. Диск резервируется также под HTML-кэш, архивы, журналы и резервные копии, поэтому его фактический расход следует измерять отдельно.

Для текущей архитектуры используйте один процесс Uvicorn: WebSocket-подключения Agent и часть состояния хранятся в памяти процесса. Простое увеличение --workers может разделить подключения между процессами и продублировать фоновые задания. Ночной сбор КХЛ получил собственную межпроцессную защиту, но это не делает всё приложение готовым к нескольким процессам.

Пример запуска из виртуального окружения:

.venv/bin/python -m uvicorn app:app --host 0.0.0.0 --port 8000 --workers 1

В production не используйте --reload. Это режим разработки с наблюдением за изменениями файлов. Если --workers не указан, Uvicorn может взять число процессов из WEB_CONCURRENCY.

Официальные справки: настройки Uvicorn, повторное использование соединений HTTPX.

Что запросить у администратора для точного диагноза

Нужны текущие vCPU/RAM, расположение PostgreSQL, число одновременно открытых матчей/браузеров и уточнение, где показаны 100%: у отдельного процесса, одного ядра, контейнера или всего сервера.

На Linux можно снять:

nproc
free -h
ps -eo pid,ppid,comm,%cpu,%mem,rss --sort=-%cpu | head -15
vmstat 1 5
top -b -n 2 -d 2

Для стандартной службы:

systemctl show khl-data.service -p NRestarts -p MemoryCurrent -p CPUUsageNSec

CPUUsageNSec — накопленное CPU-время, не процент текущей нагрузки. В обычном top 100% у одного процесса может означать одно полностью занятое ядро; показания панели VPS могут иметь другую шкалу.

Для размера базы администратор PostgreSQL может выполнить:

SELECT pg_size_pretty(pg_database_size(current_database()));

Сравнение процессов покажет, где сосредоточена нагрузка: Python веб-сервера, отдельный загрузчик КХЛ или PostgreSQL. Только после этого можно подтвердить причину предупреждения о CPU.

Проверка обновления

  • 10 новых проверок расписания, блокировки, сохранения данных/ошибок, точечного повтора и скачивания отчёта;
  • вместе с актуальными регрессионными проверками КХЛ: 46 успешных проверок;
  • два старых текстовых ожидания исключены: прежние три потока (заменено проверкой одного потока) и прежнее расположение КХЛ в настройках, изменённое ещё до этой версии;
  • интерфейс проверен в браузере: отчёт, московское время, повтор, блокировка кнопок при загрузке, ограничения зрителя и стабильность списка при фоновом опросе;
  • проверены синтаксис Python и JavaScript.

Проверки использовали локальные данные и имитации ответов. Реальный ночной запуск на вашем сервере и доступность КХЛ из его сети ещё не проверены. Снижение нагрузки КХЛ не означает, что все причины 100% CPU уже устранены.