Gunicorn / WSGI
WSGI — стандарт связи Python-приложения с веб-сервером, Gunicorn — самый популярный WSGI-сервер для production.
Что такое WSGI
WSGI (Web Server Gateway Interface, произносится «виз-ги») — стандарт, описанный в PEP 3333: как веб-сервер должен передавать HTTP-запрос Python-приложению и получать ответ.
До WSGI каждый фреймворк договаривался с каждым сервером по-своему, и связки не переставлялись. Стандарт свёл всё к одной функции:
def application(environ, start_response):
"""environ — словарь с данными запроса, start_response — колбэк для статуса и заголовков."""
start_response('200 OK', [('Content-Type', 'text/plain; charset=utf-8')])
return [b'Hello, WSGI']
Всё. Django, Flask и любой другой WSGI-фреймворк — это, если снять слои абстракций, такая же функция. Поэтому любое WSGI-приложение работает с любым WSGI-сервером: Gunicorn, uWSGI, Waitress меняются одной строкой.
Что такое Gunicorn
Gunicorn (Green Unicorn) — WSGI-сервер для production. Он занимается тем, чего не умеет manage.py runserver: держит пул рабочих процессов, распределяет между ними запросы, перезапускает зависшие и пережившие утечку памяти.
Модель — pre-fork: мастер-процесс порождает несколько воркеров, каждый обрабатывает запросы независимо. Мастер сам запросы не трогает, только следит за воркерами.
gunicorn --workers 5 --bind 127.0.0.1:8000 --timeout 60 \
--access-logfile - myproject.wsgi:application
myproject.wsgi:application — модуль и имя WSGI-объекта в нём.
Сколько воркеров ставить
Документация Gunicorn рекомендует формулу 2 × число ядер + 1. Для 4-ядерной машины — 9 воркеров.
Каждый воркер — отдельный процесс со своей копией приложения в памяти. Считайте: приложение на 200 МБ × 9 воркеров = 1.8 ГБ, и если VPS даёт 2 ГБ, OOM killer придёт за вами под нагрузкой. Формула — отправная точка, а не догма: смотрите на реальное потребление.
| Класс воркера | Когда брать |
|---|---|
sync (по умолчанию) |
обычные приложения, быстрые ответы |
gthread |
много ожидания ввода-вывода, память дорога |
gevent |
тысячи одновременных медленных соединений |
uvicorn.workers.UvicornWorker |
ASGI-приложения (FastAPI, Django async) |
WSGI или ASGI
У WSGI есть врождённое ограничение: он синхронный. Воркер занят одним запросом целиком и не может, ожидая ответа базы, взяться за следующий. Для WebSocket, server-sent events и streaming-ответов это не подходит принципиально.
Ответ — ASGI, асинхронный преемник. Его сервер — uvicorn; на нём работают FastAPI и Django в async-режиме. Для LLM-сервисов, где ответ течёт токен за токеном десятки секунд, WSGI не годится: воркер будет держать соединение и простаивать. Здесь берут ASGI или готовые серверы инференса вроде vLLM.
Практично сочетать оба — Gunicorn как мастер-процесс, uvicorn-воркеры внутри: gunicorn -k uvicorn.workers.UvicornWorker -w 4 app.main:app.
Зачем Nginx перед Gunicorn
Gunicorn — сервер приложений, а не веб-сервер. Он не отдаёт статику эффективно, не терминирует TLS и уязвим к медленным клиентам: воркер, ждущий байты от клиента на плохом мобильном интернете, занят и никого не обслуживает. Разработчики Gunicorn прямо рекомендуют ставить его за Nginx.
upstream app { server unix:/run/myapp/gunicorn.sock; }
server {
listen 80;
location /static/ { alias /srv/myapp/static/; expires 30d; }
location / {
proxy_pass http://app;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Unix-сокет вместо TCP-порта чуть быстрее и не светит приложение наружу.
Запуск как службы
В production Gunicorn запускают юнитом systemd с Restart=always — он поднимет процесс после перезагрузки и после падения. В контейнерах роль надзирателя берёт на себя Docker или Kubernetes, и Gunicorn запускают одной командой в CMD.
Связанные термины
- Python — язык, для которого создан WSGI
- Nginx — то, что ставят перед Gunicorn
- Локальный / веб-сервер — почему runserver не годится в production
- systemd / демоны — как Gunicorn держат запущенным
- OOM killer — что бывает при переборе с воркерами
- serving — то же самое для ML-моделей
Готовы запустить GPU-задачу?
Запустить GPU-сервер