Почему сайт перестаёт работать при загрузке обработчика?

В админке сайта через bulk-worker выполняется загрузка файлов: обработчик загружает файлы на S3. Во время этого сайт падает и возвращает ошибку 503, хотя база данных продолжает записывать строки — пока БД не завершит загрузку всех строк, сайт остаётся недоступен. Прикрепил два фрагмента кода: вызов и обработчик.
  • 2 апреля 2026 г. 8:00
Ответы на вопрос 3
Кратко — такое поведение обычно возникает потому, что операция загрузки/обработки выполняется синхронно в рабочих процессах веб‑сервера и блокирует их (или расходует общие ресурсы: DB‑коннекты, CPU, сеть, дескрипторы). В результате балансировщик/веб‑сервер считает приложение «недоступным» и отдаёт 503, хотя сам фоновый процесс продолжает писать в БД.

Ниже — причины, как проверить и как исправить.

Возможные причины
- Синхронная тяжёлая задача в веб‑процессе. Например, запрос в админке запускает загрузку больших файлов на S3 и занимает worker Gunicorn/Puma/uwsgi; если все рабочие заняты — новые запросы получают 503.
- Истощение пула соединений к БД. Долгие задачи держат коннекты и пул исчерпан для входящих запросов.
- Ограничение по ресурсам (CPU, сеть, память). Долгая загрузка сильно грузит сервер и health‑check/таймауты срабатывают.
- Блокирующий S3 SDK или синхронные вызовы, которые не используют асинхронный/параллельный подход.
- Балансировщик или прокси (NGINX, ELB) тайм-аутит запрос, возвращает 503/504.

Что проверить сейчас (диагностика)
1. Логи:
   - логи веб‑сервера (gunicorn/uwsgi/puma), nginx, балансировщика — есть ли сообщения об исчерпании workers, тайм‑аутах, OOM?
   - application logs — где задача стартует/завершается?
2. Состояние процессов:
   - ps/htop — сколько рабочих процессов, кто загружен CPU/IO?
   - netstat/lsof — много ли открытых сетевых соединений/файлов?
3. Статистика пула БД:
   - размер пула и сколько занято во время выполнения задачи.
4. Поведение при одновременных запросах:
   - увеличьте число коротких запросов и посмотрите, какие получают 503; какие именно процессы заняты.
5. Балансировщик/healthchecks:
   - какие healthchecks, трафик обрывается ли из‑за отсутствия ответа за лимит времени?

Быстрые исправления / обходные варианты
- Немедленное: вынести обработку в фон (background job). Запускать загрузки в отдельном воркере (Celery, Sidekiq, Resque, background job queue) и возвращать HTTP 202/200 быстро.
- Если невозможно фонить — использовать отдельный сервер/процесс для тяжёлых задач (отдельный worker pool), чтобы веб‑процессы не блокировались.
- Использовать presigned S3 URL: клиент загружает файлы напрямую в S3, сервер только сохраняет метаданные/URL — минимальная нагрузка на приложение.
- Настроить асинхронный/поточный сервер (например, Gunicorn с threads или gevent/uvicorn), но это требует проверки совместимости с кодом и с драйверами БД.
- Увеличить число веб‑воркеров/пулов и/или размер пула DB (временно), если ресурсы позволяют, чтобы не исчерпать capacity.
- Ограничивать параллелизм внутри обработчика (например, не запускать 100 одновременных загрузок на одной машине).

Рекомендации по правкам кода (общие)
- Не делать долгие network/IO операции прямо в обработчике запроса.
- Если используете Python + boto3: не вызывать upload_file в основном потоке без фонового воркера; вместо этого отправляйте задачу в Celery или генерируйте presigned_post.
- Освобождать DB‑соединения как можно быстрее (commit/close) и не держать транзакции во время сетевых загрузок.

Что мне нужно от вас, чтобы дать конкретный совет
- Пришлите, пожалуйста, оба фрагмента кода (вызов и обработчик), и укажите:
  - на чём сайт (язык/фреймворк — Python/Django/Flask, Ruby/Rails и т.д.);
  - какой веб‑сервер/процесс менеджер (Gunicorn/uWSGI/Puma/Unicorn) и конфигурация (кол‑во workers, threads);
  - как запускается bulk‑worker (в том же процессе, отдельный скрипт, очередь задач?);
  - используемый S3‑клиент/библиотека;
  - что возвращают логи при падении (обрыв, таймауты, “worker timed out” и т.п.).
С этим я смогу указать точный узел проблемы и предложить изменения в коде/конфигурации.

Если хотите — могу сразу показать пример того, как перенести загрузку в Celery (или как сделать presigned URL) в вашем стеке — пришлите стек и фрагменты кода.
классика — обработка в веб-реквесте жрёт все php-fpm воркеры и сайту не на чем отвечать. Вынеси в фон: cli-скрипт по крону или очередь на redis. В вебе только сохраняй задание в бд и показывай прогресс.
<blockquote>Пока не загрузит бд все строки, сайт не заработает.</blockquote> <br/> Это типичная проблема блокировки сессии. Можно легко проверить, если запустить ваш админский скрипт, а потом попробовать открыть сайт в инкогнито. Если открывается, значит нужно в вашем скрипте закрыть сессию перед началом длительных операций. <br/> <br/> <pre><code class="php">&lt;?php
// /admin/bulk-worker.php - Обработчик с загрузкой фото на S3

session_name('СЕССИЯ');
session_start();

error_reporting(E_ALL);
ini_set('display_errors', 1);
set_time_limit(0);

require_once '../includes/config.php';
require_once '../includes/s3-upload.php';

// Проверка доступа
if (!isset($_SESSION['is_admin']) || $_SESSION['is_admin'] != 1) {
    die('Доступ запрещен');
}

session_write_close(); // &lt;------- например, вот здесь</code></pre>
Похожие вопросы