Каким образом Django связан с Nginx и Gunicorn?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Django, Nginx и Gunicorn: Architecture и взаимодействие
Это классический стек для production Django приложений. Нужно понимать, как они работают вместе и зачем каждый нужен.
Архитектура: OSI Model
Client Browser Internet
|
| HTTP/HTTPS request
↓
┌─────────────────┐
│ NGINX │ ← Web server (reverse proxy)
│ :80, :443 │ - Load balancing
└────────┬────────┘ - SSL/TLS termination
| - Static files
| TCP 8000
↓
┌──────────────────────────────────────────┐
│ Gunicorn (WSGI Application Server) │
│ │
│ Worker 1 Worker 2 Worker 3 Worker 4 │ ← Process pool
│ | | | | │
│ └──────────┼─────────┼─────────┘ │
│ | | │
│ ┌─────┴─────────┴──┐ │
│ | Django App | │
│ └──────────────────┘ │
└──────────────────────────────────────────┘
|
| Database connection
↓
PostgreSQL
Роль каждого компонента
1. NGINX: Web Server (Layer 7)
NGINX — это reverse proxy. Он:
✅ Принимает HTTP запросы на портах 80 (HTTP) и 443 (HTTPS) ✅ Обрабатывает SSL/TLS — шифрует/дешифрует ✅ Раздаёт static файлы (CSS, JS, images) без Django ✅ Load balancing — распределяет запросы между Gunicorn workers ✅ Caching — может кешировать ответы ✅ Compression — gzip сжатие ответов ✅ URL routing — может route разные domains
Конфиг NGINX:
upstream django {
# Balancing между 4 Gunicorn workers
server 127.0.0.1:8000;
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
}
server {
listen 80;
server_name example.com;
# Редирект на HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/ssl/certs/cert.pem;
ssl_certificate_key /etc/ssl/private/key.pem;
# Static файлы (не идут в Django)
location /static/ {
alias /var/www/static/;
expires 30d;
}
# Media файлы (uploaded users)
location /media/ {
alias /var/www/media/;
expires 7d;
}
# Всё остальное -> Gunicorn
location / {
proxy_pass http://django;
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;
# Timeouts
proxy_read_timeout 30s;
proxy_connect_timeout 10s;
}
}
2. Gunicorn: WSGI Application Server
Gunicorn (Green Unicorn) — это application server.
✅ Запускает Django приложение ✅ Создаёт worker processes (обычно 4 = 2 * CPU cores) ✅ Слушает на localhost:8000 (не открыт в интернет!) ✅ WSGI совместимый (работает с Flask, Django, etc.) ✅ Graceful restart — рестарт без потери запросов ✅ Preload app — память разделяется между workers
Запуск Gunicorn:
# Simple
gunicorn myproject.wsgi:application --bind 0.0.0.0:8000 --workers 4
# Production
gunicorn myproject.wsgi:application \
--bind 0.0.0.0:8000 \
--workers 4 \
--worker-class sync \
--worker-connections 1000 \
--max-requests 1000 \
--max-requests-jitter 50 \
--timeout 30 \
--access-logfile /var/log/gunicorn/access.log \
--error-logfile /var/log/gunicorn/error.log \
--log-level info \
--daemon
Systemd service:
[Unit]
Description=Gunicorn Django Application
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/app
ExecStart=/usr/bin/gunicorn \
--workers 4 \
--bind 127.0.0.1:8000 \
--log-level info \
myproject.wsgi:application
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
3. Django: Web Framework
Django — это приложение, которое WSGI-compliant.
# myproject/wsgi.py
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = get_wsgi_application()
# Это WSGI callable, которую вызывает Gunicorn
Что Django делает:
- Обрабатывает HTTP запрос
- Маршрутизирует (urls.py)
- Вызывает view
- Обращается к БД
- Возвращает HTTP response
Поток запроса
Client Browser
|
| GET /api/users/1
↓
NGINX (0.0.0.0:443)
| Проверка SSL: OK
| Is static? NO
| URL pattern: /api/users/1 → Django
| Load balance: → Worker 2 on port 8000
|
↓ TCP 127.0.0.1:8000
Gunicorn Worker 2
|
| Запуск WSGI приложение
| Передача request → Django
↓
Django (application callable)
|
| URL routing: /api/users/1 → UserViewSet.retrieve
| Обработка request
| Query: SELECT * FROM users WHERE id=1
|
↓ Database
PostgreSQL
|
| SELECT * FROM users WHERE id=1
| Return: {"id": 1, "name": "Alice", ...}
↓
Django
|
| Serialization (UserSerializer)
| Response: {"id": 1, "name": "Alice", "email": "alice@example.com"}
↓
Gunicorn Worker 2
|
| Return response to NGINX
↓
NGINX
|
| Gzip compression
| Add headers (Cache-Control, ETag, etc.)
| Return to client
↓
Client Browser
|
| Response: 200 OK
| Body: {"id": 1, "name": "Alice", ...}
Важные детали
1. WSGI Protocol
WSGI (Web Server Gateway Interface) — это стандарт Python для web apps.
# WSGI callable должна принимать:
# - environ: dict с request info
# - start_response: callback для отправки headers
def simple_wsgi_app(environ, start_response):
# environ['REQUEST_METHOD'] → 'GET'
# environ['PATH_INFO'] → '/api/users'
# environ['QUERY_STRING'] → 'page=1'
response_headers = [
('Content-Type', 'application/json'),
('Content-Length', '13'),
]
start_response('200 OK', response_headers)
return [b'{"status": "ok"}']
Django предоставляет get_wsgi_application(), которая возвращает такой callable.
2. Process Pool Model
Gunicorn использует multi-process model:
GMaster Process (PID: 1000)
|
├─ Worker 1 (PID: 1001) ← Обрабатывает 1 request в раз
├─ Worker 2 (PID: 1002) ← Обрабатывает 1 request в раз
├─ Worker 3 (PID: 1003) ← Обрабатывает 1 request в раз
└─ Worker 4 (PID: 1004) ← Обрабатывает 1 request в раз
Если приходит 5 requests:
Request 1 → Worker 1 (processing)
Request 2 → Worker 2 (processing)
Request 3 → Worker 3 (processing)
Request 4 → Worker 4 (processing)
Request 5 → Queue (waiting)
Почему multiple workers:
- ✅ I/O blocking: если Worker 1 ждет БД, Worker 2 может обработать другой request
- ✅ Throughput: 4 workers = ~4x requests/sec
- ✅ Resilience: если 1 worker crash, остальные работают
3. Static Files
NGINX обрабатывает static файлы, не Django:
# Django settings.py
STATIC_ROOT = '/var/www/static/'
STATIC_URL = '/static/'
# Collect static
# python manage.py collectstatic
# NGINX config
location /static/ {
alias /var/www/static/; # Прямой доступ к файлам
expires 30d; # Кеш на 30 дней
}
Почему так:
- ❌ Django (Python) медленнее для static файлов
- ✅ NGINX делает это с 10x скоростью
- ✅ Экономит процессы Django
4. Graceful Reload
# Restart без downtime
gunicorn reload
# Процесс:
# 1. Master process получает SIGHUP
# 2. Master создаёт new workers с new code
# 3. Old workers дорешают current requests
# 4. Old workers завершаются
# Result: Zero downtime!
5. Timeouts
# NGINX config
proxy_read_timeout 30s; # Ждём 30s ответ от Django
proxy_connect_timeout 10s; # Ждём 10s на подключение
# Gunicorn config
--timeout 30 # Worker умирает если не ответит за 30s
Если Worker зависнет:
- Gunicorn master убивает worker
- NGINX видит разорванное соединение
- NGINX перенаправляет request на другой worker
6. Load Balancing
upstream django {
# Round-robin (по умолчанию)
server 127.0.0.1:8000;
server 127.0.0.1:8001;
# Least connections (нагруженность)
least_conn;
server 127.0.0.1:8000;
server 127.0.0.1:8001;
# IP hash (sticky session)
ip_hash;
server 127.0.0.1:8000;
server 127.0.0.1:8001;
}
Типичные проблемы и решения
Проблема 1: 502 Bad Gateway
NGINX говорит: не могу подключиться к Django
Причины:
- Gunicorn не запущен
- Gunicorn упал
- Порт неправильный
Решение:
sudo systemctl status gunicorn
sudo systemctl restart gunicorn
Проблема 2: Worker Timeout
Long-running request (>30s) kills worker
Причины:
- Медленный SQL query
- Тяжелая обработка данных
Решение:
- Оптимизировать query (добавить index)
- Использовать Celery для async tasks
- Увеличить timeout (аккуратно)
Проблема 3: Out of Memory
Workers растут в памяти со временем
Причины:
- Memory leak в коде
- Кеш растет
Решение:
настроить max-requests restart:
--max-requests 1000 # Restart worker после 1000 requests
--max-requests-jitter 50 # +random(0-50) to avoid spikes
Production Setup
# 1. NGINX
sudo systemctl start nginx
sudo systemctl enable nginx # Auto-start
# 2. Gunicorn
sudo systemctl start gunicorn
sudo systemctl enable gunicorn # Auto-start
# 3. Django
cd /app
python manage.py migrate # Миграции БД
python manage.py collectstatic # Static files
# 4. Check
ps aux | grep nginx # NGINX процесс
ps aux | grep gunicorn # Gunicorn процессы
curl http://127.0.0.1:8000/api/ # Django работает?
# 5. Monitor
tail -f /var/log/nginx/error.log
tail -f /var/log/gunicorn/error.log
Architecture Decisions
Почему 3-слойная архитектура?
NGINX (reverse proxy)
↓
Gunicorn (app server)
↓
Django (business logic)
Вместо:
Django directly (bad for production)
✗ No SSL termination
✗ Slow static files
✗ Can't load balance
✗ Single process (bottleneck)
Альтернативы
1. uWSGI вместо Gunicorn
- Similar, но более heavy
- Более features
2. Docker + containerization
- Легче deploy
- Isolation
3. Kubernetes
- Auto-scaling
- Load balancing at container level
- Для enterprise
Резюме
NGINX + Gunicorn + Django — классическая production архитектура:
- ✅ NGINX: Обрабатывает HTTP, SSL, static, load balancing
- ✅ Gunicorn: Запускает multiple workers Django процессов
- ✅ Django: Бизнес логика, DB обращения, API endpoints
Flow:
Client Browser
↓ HTTP request
NGINX (0.0.0.0:443)
↓ TCP 127.0.0.1:8000
Gunicorn Worker (load balanced)
↓
Django Application
↓
PostgreSQL Database
Key Concepts:
- WSGI protocol — interface between web server и app
- Multi-process model — throughput и resilience
- Static files in NGINX — performance
- Graceful reload — zero downtime updates
- Timeouts — prevent hanging requests
Эта архитектура используется в тысячах Django проектов и proven в production.