Выберите продукт

uWSGI vs Gunicorn: что выбрать для Python‑проекта на VDS

uWSGI и Gunicorn решают одну задачу — поднимать WSGI‑приложение быстро и устойчиво. Но под нагрузкой, по памяти и удобству они ведут себя по‑разному. Разбираем, что выбрать на VDS, какие воркеры и таймауты задать, как настраивать Nginx и systemd и перезапускать без простоя.
uWSGI vs Gunicorn: что выбрать для Python‑проекта на VDS

Если у вас Python‑приложение и на VDS пора выходить в прод, выбор между uWSGI и Gunicorn возникает почти всегда. Оба сервера реализуют WSGI, оба давно в продакшене, но различаются философией, моделью воркеров, набором возможностей и ценой в администрировании. Ниже — практичное сравнение для админов и девопсов: как повлиять на производительность и стабильно жить под Nginx и systemd.

Кратко: когда какой сервер

Сразу ответ для тех, кто спешит:

  • Gunicorn — минимализм и предсказуемость. Отличный выбор для Django/Flask, когда нужны простые синхронные воркеры, быстрая интеграция с Nginx и прозрачные перезапуски. Также Gunicorn часто используют как менеджер для ASGI через воркеры Uvicorn.
  • uWSGI — «швейцарский нож». Море настроек, Emperor/Vassals для множественных приложений, offload, spooler, «cheaper»‑алгоритмы экономии RAM. Требует дисциплины в конфигурации, но раскрывается на плотных VDS со множеством сервисов.

Для ASGI‑приложений (FastAPI/Starlette) обычно берут Uvicorn, нередко в связке с Gunicorn как процесс‑менеджером. uWSGI — про WSGI в первую очередь.

Архитектура и модель воркеров

Gunicorn

Gunicorn запускает мастер‑процесс и пул воркеров. По умолчанию — синхронные воркеры на основе prefork. Есть альтернативы: gevent, eventlet, gthread, а для ASGI — воркеры Uvicorn. Конфигурация через флаги командной строки или Python‑конфиг. Философия: минимально необходимый набор, остальное — через воркеры и экосистему.

uWSGI

uWSGI — это не только сервер приложений, но и обширная платформа (плагины, режим Emperor/Vassals, internal routing, offload threads, spooler для задач и т. д.). Конфиги в INI/YAML‑стиле, множество опций, несколько способов двухфазного перезапуска. Есть встроенные механики снижения потребления памяти при простое (семейство опций cheaper).

Схема Nginx как reverse proxy к Gunicorn по UNIX‑сокету

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

Латентность и RPS упираются в несколько факторов:

  • тип воркеров (синхронные vs асинхронные),
  • число воркеров и потоков,
  • Copy‑on‑write и preload_app,
  • стоимость сериализации ответа/шаблонов,
  • проксирование (Nginx), сокеты (UNIX vs TCP),
  • таймауты и очереди (listen backlog).

На CPU‑ограниченных VDS синхронные воркеры показывают предсказуемую латентность при CPU‑bound задачах. Для I/O‑bound чаще выигрывают gthread или gevent/Uvicorn‑воркеры (Gunicorn) либо асинхронная модель на стороне приложения. uWSGI предоставляет собственные твики, но выигрыш зависит от конкретной нагрузки.

UNIX‑сокет или TCP

Если Nginx и приложение на той же машине, выбирайте UNIX‑сокет: меньше накладных расходов и нет TCP‑стека между процессами. Следите за правами на сокет и директорией, где он создаётся.

Copy‑on‑write и preload

И Gunicorn, и uWSGI умеют предварительно загружать приложение в мастере (Gunicorn: --preload, uWSGI: lazy-apps и родственные). Это экономит RAM за счёт copy‑on‑write, ускоряет форк воркеров и даёт стабильную латентность на старте воркера. Не забывайте, что любые записи в глобальные структуры после preload ломают выгоду от CoW.

Конфигурация: насколько сложна

Gunicorn: минимум, который работает

Базовый старт для Django/Flask — одна строка, параметры легко вынести в systemd‑юнит. Конфигурационный файл в Python позволяет держать все опции рядом с кодом.

uWSGI: мощно, но многословно

uWSGI предлагает десятки ключей. Это плюс, когда нужно тонко управлять воркерами, проводить перезапуски без потери соединений, запускать много приложений через Emperor. Но из‑за широты опций выше риск случайно ввести противоречивые настройки. Рекомендуется формализовать «профили» под типовой стек (Django sync, Flask + threads и т. п.).

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Интеграция с Nginx

Типовой паттерн: Nginx принимает внешние соединения, терминирует TLS, кэширует статику и проксирует на Gunicorn/uWSGI по UNIX‑сокету. Убедитесь, что согласованы client_max_body_size, proxy_read_timeout и таймауты приложения, иначе получите 499/504 под нагрузкой. Если параллельно переводите сайт на HTTPS и HSTS, пригодится наш разбор по переносу домена и политикам безопасности — смотрите материал «Перенос домена с 301 и HSTS» (как мигрировать и включить HSTS). Для выпуска и установки сертификатов используйте SSL-сертификаты.

# Фрагмент server для Nginx (проксирование к UNIX-сокету)
location / {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_pass http://unix:/run/app.sock;
    proxy_read_timeout 60s;
    proxy_send_timeout 60s;
}

Если используете uWSGI‑протокол, возможен uwsgi_pass, но HTTP через proxy_pass универсальнее и проще для отладки.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Выбор типов воркеров и формул

  • Синхронные (по умолчанию в Gunicorn, аналог в uWSGI): хороши для CPU‑bound и простых I/O, предсказуемая латентность.
  • gthread (Gunicorn) и потоки в uWSGI: помогают при умеренной I/O‑нагрузке с блокирующими вызовами.
  • gevent/eventlet (Gunicorn) или асинхронные режимы в uWSGI: уместны, если библиотека совместима с monkey patching и нагрузка преимущественно I/O.

Базовая оценка числа воркеров для синхронных процессов: workers = 2 × CPU + 1. Для потоков — меньше воркеров, больше потоков. Для Uvicorn‑воркеров под ASGI — отталкивайтесь от I/O, часто 1–2 воркера на ядро достаточно.

Перезапуски без простоя

Оба сервера поддерживают graceful‑перезапуск: мастер перестаёт принимать новые коннекты, ждёт завершения активных запросов и перезапускает воркеры. Если готовите релиз с минимальным простоем, пригодится пошаговый гид про миграцию без даунтайма — см. материал «Миграция проекта без простоя» (чек‑лист с этапами).

  • Gunicorn: сигнал HUP перечитывает конфиг, USR2 — zero‑downtime перезапуск с новым мастером.
  • uWSGI: разные стратегии через touch-reload, die-on-term, двойной мастер и др. Emperor даёт перезапуск отдельных «вассалов».

Логирование и метрики

Оба сервера пишут access/error‑логи. Для метрик популярны statsd/Prometheus‑сборщики через сторонние экспортеры или плагины. Главное — не забывать про ротацию логов и log-level на проде, чтобы не тратить CPU и диск на болтливость.

Безопасность и изоляция

  • Запускайте под отдельным пользователем, не под root.
  • UNIX‑сокет в каталоге с ограниченными правами, корректные umask и владельцы.
  • Ограничьте nofile и память через systemd или cgroups.
  • Не держите отладку и подробные traceback в продакшене.

Примеры конфигураций

Gunicorn + systemd

[Unit]
Description=Gunicorn for myapp
After=network.target

[Service]
User=app
Group=app
WorkingDirectory=/srv/myapp
Environment="PATH=/srv/myapp/venv/bin"
ExecStart=/srv/myapp/venv/bin/gunicorn wsgi:app --workers 4 --bind unix:/run/myapp.sock --timeout 60 --graceful-timeout 60 --access-logfile - --error-logfile -
RuntimeDirectory=myapp
RuntimeDirectoryMode=0750
KillMode=mixed
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

Проверьте, что директория /run создаётся systemd (через RuntimeDirectory), иначе сокет некуда положить. Для Python‑конфига Gunicorn можно вынести опции из строки ExecStart, чтобы не разрасталась. Если управляете сервером через панель, сравнение актуальных панелей для админов — в статье «Сравнение панелей для VDS» (что выбрать в 2025).

uWSGI Emperor + vassal

# /etc/systemd/system/uwsgi-emperor.service
[Unit]
Description=uWSGI Emperor
After=network.target

[Service]
User=uwsgi
Group=uwsgi
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --die-on-term --log-format "%(method) %(uri) %(status) %(msecs)ms"
Restart=on-failure
KillMode=mixed
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
# /etc/uwsgi/vassals/myapp.ini
[uwsgi]
chdir = /srv/myapp
module = wsgi:app
master = true
processes = 4
threads = 1
socket = /run/myapp.sock
chmod-socket = 660
vacuum = true
die-on-term = true
harakiri = 60
buffer-size = 65535
max-requests = 5000
reload-on-as = 512
reload-on-rss = 384
# Для graceful-перезагрузки достаточно тронуть файл
touch-reload = /srv/myapp/reload

# Экономия памяти при простое
cheaper = 2
cheaper-initial = 2
cheaper-step = 1

# Логи
disable-logging = false

Режим Emperor удобен, когда на одном VDS несколько сервисов. Для одиночного приложения можно обойтись без Emperor и поднять единичный service‑юнит с конкретным --ini.

Примеры unit‑файлов systemd для Gunicorn и uWSGI Emperor

Методика мини‑бенчмарка

Чтобы не спорить «на вкус», сравните у себя. Простейший план:

  1. Отключите все фоновые джобы, чтобы не шумели на CPU и диске.
  2. Поднимите Nginx + сервер приложений на одном VDS.
  3. Замерьте четыре режима: Gunicorn sync, Gunicorn gthread, uWSGI processes+threads, uWSGI только процессы.
  4. Снимите метрики RPS и p95/p99 lat, CPU iowait, ошибки 5xx/499.
# Пример однопоточного обстрела
wrk -t4 -c128 -d60s http://127.0.0.1/

# Наблюдать ресурсы
pidstat -ruhl 1
ss -lntp

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

Таймауты, очереди и лимиты

  • Таймаут запроса: в Gunicorn --timeout, в uWSGI harakiri. Должны быть согласованы с proxy_read_timeout в Nginx.
  • Очередь сокета: увеличьте listen backlog (uWSGI: listen, Gunicorn уважает системный somaxconn), чтобы не терять пики.
  • Размер буфера: uWSGI buffer-size для длинных заголовков, иначе 502. В Nginx настройте large_client_header_buffers.
  • Ограничения файлов: увеличьте LimitNOFILE и системный fs.file-max, если много соединений.

Память и Copy‑on‑write

Оцените базовую RAM на воркер: при preload у Gunicorn на Python 3.11 типично 20–60 МБ на воркер для простого Flask/Django. В uWSGI — сопоставимо, но cheaper уменьшает общее число процессов при простое. Следите за метрикой RSS на воркерах и перезапускайте при утечках (max-requests у обоих серверов помогает ограничить рост).

Отладка и диагностика

  • Проверьте права сокета и каталога. Частая причина 502 — Nginx не может открыть UNIX‑сокет.
  • Смотрите error‑логи сервера приложений и Nginx: несогласованные таймауты и размер заголовков видны сразу.
  • Включите access‑лог с латентностью в мс, чтобы ловить хвосты p95/p99.
  • Проверяйте GC‑паузы и кумулятивное время в логике приложения — сервер приложений не лечит медленный код.

Сравнение по критериям

  • Простота: Gunicorn выигрывает. Один бинарь, понятные флаги, прогнозируемое поведение.
  • Гибкость: uWSGI впереди — Emperor, offload, spooler, тонкая настройка маршрутизации.
  • ASGI: Gunicorn как менеджер для Uvicorn популярен; uWSGI ориентирован на WSGI.
  • Память: сопоставимо, но uWSGI «cheaper» удобен на VDS со сменной нагрузкой.
  • Перезапуски: оба умеют graceful и zero‑downtime, у uWSGI больше стратегий.
  • Кривая обучения: у uWSGI выше — много опций и нюансов совместимости.

Практические пресеты

Django/Flask, синхронно, 2 vCPU

  • Gunicorn: 5 воркеров (2 × 2 + 1), --timeout 60, UNIX‑сокет.
  • uWSGI: processes = 5, threads = 1, harakiri = 60, cheaper = 2.

I/O‑heavy, блокирующие библиотеки

  • Gunicorn: 2 воркера на vCPU, --worker-class gthread, --threads 8.
  • uWSGI: меньше процессов, больше threads, проверьте GIL‑сценарии.

ASGI (FastAPI/Starlette)

  • Gunicorn с воркерами Uvicorn: 1–2 воркера на ядро, --worker-class uvicorn.workers.UvicornWorker, тюньте --graceful-timeout.

Частые ошибки и как их избежать

  • Несогласованные таймауты: 504 в Nginx при долгом рендере страниц. Согласуйте proxy_read_timeout и harakiri/--timeout.
  • Перегрузка очереди: при пиках теряются соединения. Увеличьте backlog и количество воркеров, закупорьте «тяжёлые» пути кэшем.
  • Логи душат диск: на пике JSON‑лог в учётной системе может съесть CPU. Уменьшайте детализацию, включайте ротацию.
  • Память утекает: включите max-requests и отслеживайте RSS. Не лечит первопричину, но стабилизирует сервис.
  • Неправильные права на сокет: Nginx от имени www-data не читает сокет приложения — настройте chmod-socket и группу.

Итоговые рекомендации

Если нужен быстрый и понятный старт, минимум движущихся частей и хорошие дефолты — выбирайте Gunicorn. Он отлично дружит с Nginx и systemd, предсказуем в поведении и логировании, легко масштабируется по воркерам. Если у вас сложный многосервисный хост, важна экономия памяти на простое, нужны встроенные механики вроде Emperor, cheaper, spooler и тонкая маршрутизация — присмотритесь к uWSGI. По чистой производительности на равных настройках разницы часто нет, выигрывает тот, кто точнее настроен под вашу нагрузку.

Не поленитесь провести локальный бенч и зафиксировать пресет параметров для своего профиля трафика. Это окупается: предсказуемая латентность, понятные перезапуски, отсутствие 502/504 в пике и экономия памяти на VDS.

Поделиться статьей

Вам будет интересно

Caddy vs Nginx Unit vs Apache mod_php в 2026 году: что выбрать для PHP-сайта OpenAI Статья написана AI (GPT 5)

Caddy vs Nginx Unit vs Apache mod_php в 2026 году: что выбрать для PHP-сайта

Для небольшого PHP-сайта в 2026 году выбор уже не сводится к схеме Nginx и PHP-FPM. Разбираю Caddy, Nginx Unit и Apache mod_php с ...
Dovecot vs Courier vs Stalwart Mail Server в 2026: что выбрать для self-hosted почты на VDS OpenAI Статья написана AI (GPT 5)

Dovecot vs Courier vs Stalwart Mail Server в 2026: что выбрать для self-hosted почты на VDS

Если вы поднимаете собственную почту на VDS, выбор между Dovecot, Courier и Stalwart влияет не только на IMAP-доступ, но и на сопр ...
Podman vs Docker Compose vs systemd units в 2026: что выбрать для self-hosted на одном сервере OpenAI Статья написана AI (GPT 5)

Podman vs Docker Compose vs systemd units в 2026: что выбрать для self-hosted на одном сервере

Для self-hosted-проектов на одном сервере выбор между Podman, Docker Compose и systemd units влияет не только на запуск, но и на о ...