Настройка Gunicorn: конфигурация, оптимизация и развертывание | AdminWiki

Настройка Gunicorn: Полное руководство для production-развертывания Python-приложений

18 декабря 2025 9 мин. чтения #Deployment #Gunicorn #devops #nginx #python #systemd #wsgi
Содержание статьи

Развертывание Python-приложения в production — это не просто python app.py. Когда твое приложение начинает получать реальный трафик, тебе нужен надежный, масштабируемый и производительный WSGI-сервер. Давай разберем, как правильно настроить Gunicorn, чтобы твое приложение работало стабильно под нагрузкой.

Что такое Gunicorn и зачем он нужен?

Gunicorn (Green Unicorn) — это WSGI HTTP-сервер для Python, написанный на чистом Python. Он работает как прокси между твоим веб-сервером (Nginx/Apache) и Python-приложением. Основные преимущества:

  • Простота настройки: Минимальная конфигурация для старта
  • Производительность: Использует pre-fork worker модель
  • Совместимость: Работает с любым WSGI-совместимым фреймворком (Django, Flask, FastAPI через специальные воркеры)
  • Надежность: Автоматическое перезапуск упавших воркеров
Важно: Gunicorn не предназначен для обслуживания статических файлов в production. Всегда используй его в связке с Nginx или другим веб-сервером, который будет раздавать статику и работать как reverse proxy.

Установка и базовая настройка Gunicorn

Установка через pip

bash
# Установка в виртуальное окружение
pip install gunicorn

# Или с указанием версии
pip install gunicorn==20.1.0

Базовый запуск приложения

Представь, что у тебя есть Flask-приложение в файле app.py:

python
# app.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello, World!'

Запуск Gunicorn с базовыми параметрами:

bash
# Базовый запуск
# app:app — модуль:экземпляр приложения
gunicorn app:app

# С указанием хоста и порта
gunicorn --bind 0.0.0.0:8000 app:app

# С 4 воркерами
gunicorn --workers 4 --bind 0.0.0.0:8000 app:app

Конфигурационные файлы Gunicorn

Для production-развертывания используй конфигурационные файлы вместо передачи параметров через командную строку.

Python-конфигурация (gunicorn.conf.py)

python
# gunicorn.conf.py
import multiprocessing

# Базовые настройки
bind = "0.0.0.0:8000"
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = "sync"

# Логирование
accesslog = "-"  # stdout
errorlog = "-"   # stdout
loglevel = "info"

# Таймауты
timeout = 30
keepalive = 2

# Безопасность
limit_request_line = 4096
limit_request_fields = 100
limit_request_field_size = 8190

# Перезагрузка при изменении кода (только для development!)
reload = False

Запуск с конфигурационным файлом

bash
# Указание конфигурационного файла
gunicorn -c gunicorn.conf.py app:app

# Или если файл называется по-другому
gunicorn --config python:config.gunicorn app:app

Оптимизация воркеров Gunicorn

Выбор правильного типа и количества воркеров — ключ к производительности.

Типы воркеров

Тип воркера Описание Когда использовать
sync Синхронный (по умолчанию) Быстрые, CPU-intensive задачи
gevent Асинхронный на основе greenlets Много I/O операций, WebSockets
eventlet Асинхронный (альтернатива gevent) Аналогично gevent
gthread Потоковый воркер Приложения с GIL-блокировками
uvicorn.workers.UvicornWorker Для ASGI приложений (FastAPI) FastAPI, Starlette, ASGI-приложения

Расчет количества воркеров

python
# Оптимальная формула для CPU-bound задач
workers = (2 * cpu_cores) + 1

# Для I/O bound задач можно увеличить
# Пример для 4-ядерного процессора:
import multiprocessing

cpu_cores = multiprocessing.cpu_count()  # 4
workers = cpu_cores * 2 + 1              # 9 воркеров

# Для gevent/eventlet устанавливаем большое количество соединений
worker_connections = 1000
Внимание: Слишком большое количество воркеров может привести к исчерпанию памяти. Мониторь использование памяти каждого воркера и настраивай количество соответственно.

Конфигурация для разных типов приложений

python
# Для Django (синхронный)
workers = 3
worker_class = "sync"
timeout = 30

# Для Flask с I/O операциями
workers = 2
worker_class = "gevent"
worker_connections = 1000

# Для FastAPI (ASGI)
workers = 4
worker_class = "uvicorn.workers.UvicornWorker"

# Для CPU-intensive приложений
workers = multiprocessing.cpu_count()
worker_class = "sync"
threads = 2  # если используешь gthread

Интеграция с systemd для автозапуска

Для production-сервера настрой автозапуск через systemd.

Создание systemd сервиса

config
# /etc/systemd/system/myapp.service
[Unit]
Description=Gunicorn instance for myapp
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/myapp
Environment="PATH=/var/www/myapp/venv/bin"
ExecStart=/var/www/myapp/venv/bin/gunicorn \
          --config /var/www/myapp/gunicorn.conf.py \
          app:app

# Перезагрузка при сбое
Restart=always
RestartSec=3

# Лимиты ресурсов
LimitNOFILE=65535
LimitNPROC=65535

[Install]
WantedBy=multi-user.target

Управление сервисом

bash
# Перезагрузка systemd
sudo systemctl daemon-reload

# Запуск сервиса
sudo systemctl start myapp

# Автозапуск при загрузке
sudo systemctl enable myapp

# Проверка статуса
sudo systemctl status myapp

# Просмотр логов
sudo journalctl -u myapp -f

Настройка Nginx как reverse proxy

Nginx будет принимать HTTP-запросы и проксировать их на Gunicorn.

config
# /etc/nginx/sites-available/myapp
server {
    listen 80;
    server_name example.com;

    # Статические файлы
    location /static/ {
        alias /var/www/myapp/static/;
        expires 30d;
    }

    location /media/ {
        alias /var/www/myapp/media/;
        expires 30d;
    }

    # Проксирование на Gunicorn
    location / {
        proxy_pass http://127.0.0.1:8000;
        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_connect_timeout 75s;
        proxy_send_timeout 3600s;
        proxy_read_timeout 3600s;
    }

    # Запрет доступа к скрытым файлам
    location ~ /\. {
        deny all;
    }
}

Мониторинг и логирование

Настройка логов Gunicorn

python
# В gunicorn.conf.py
import logging
import sys

# Файлы для логов
accesslog = "/var/log/gunicorn/access.log"
errorlog = "/var/log/gunicorn/error.log"
loglevel = "info"

# Формат логов
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'

# Кастомный логгер для ошибок
logger_class = "myapp.logging.CustomLogger"

# Захват stdout/stderr
capture_output = True
enable_stdio_inheritance = False

Мониторинг метрик

Gunicorn предоставляет статистику через арбитр (arbiter):

bash
# Отправка сигналов для получения статистики
# Получение информации о воркерах
kill -TTIN $(cat /var/run/gunicorn.pid)

# Graceful перезагрузка
kill -HUP $(cat /var/run/gunicorn.pid)

# Просмотр PID мастер-процесса
cat /var/run/gunicorn.pid

Продвинутые настройки и оптимизации

Настройка для высоких нагрузок

python
# gunicorn.conf.py для high-load
import multiprocessing

# Базовые настройки
bind = "0.0.0.0:8000"
workers = multiprocessing.cpu_count() * 3
worker_class = "gevent"
worker_connections = 2000

# Оптимизация производительности
max_requests = 1000
max_requests_jitter = 50

# Keep-alive
keepalive = 5

# Безопасность и лимиты
backlog = 2048
limit_request_line = 4096
limit_request_fields = 100

# Graceful shutdown
graceful_timeout = 30
timeout = 120

# Preload приложения для экономии памяти
preload_app = True

# Установка nice значения
# (только если запускаешь от root)
# pidfile = "/var/run/gunicorn.pid"
# umask = 0o007
# user = "www-data"
# group = "www-data"

Docker-конфигурация

Dockerfile
FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# Создание пользователя для безопасности
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser

# Запуск Gunicorn
CMD ["gunicorn", "--config", "gunicorn.conf.py", "app:app"]

Типичные проблемы и их решение

1. Воркеры умирают из-за таймаута

Решение: Увеличь timeout в конфигурации. Для долгих операций (загрузка файлов, API-запросы) установи timeout = 120 или больше.

2. Высокое потребление памяти

Симптомы: воркеры постоянно перезапускаются, система использует swap.

python
# Решения:
# 1. Уменьши количество воркеров
workers = 2  # вместо workers = cpu_count * 2 + 1

# 2. Включи preload_app
preload_app = True

# 3. Используй max_requests для периодического перезапуска
max_requests = 1000
max_requests_jitter = 100

3. Медленная загрузка статических файлов

Помни: Gunicorn не оптимизирован для раздачи статики. Всегда настраивай Nginx/Apache для обслуживания /static/ и /media/ путей.

4. 502 Bad Gateway от Nginx

Проверь:

  • Запущен ли Gunicorn: sudo systemctl status myapp
  • Слушает ли порт: sudo netstat -tlnp | grep 8000
  • Правильность proxy_pass в Nginx конфиге
  • Достаточно ли памяти/CPU

Проверка и тестирование конфигурации

bash
# Проверка синтаксиса конфигурационного файла
gunicorn --check-config -c gunicorn.conf.py app:app

# Тестовый запуск в foreground
gunicorn --config gunicorn.conf.py app:app

# Проверка количества воркеров после запуска
ps aux | grep gunicorn

# Проверка открытых портов
sudo ss -tlnp | grep :8000

# Тестирование под нагрузкой (установи ab или wrk)
ab -n 1000 -c 10 http://localhost:8000/

Безопасность Gunicorn

  • Запуск от непривилегированного пользователя: Никогда не запускай Gunicorn от root
  • Изоляция: Используй virtualenv или Docker для изоляции зависимостей
  • Файловые permissions: Правильно настрой права на конфигурационные файлы и логи
  • Биндинг: В production биндись только на localhost (127.0.0.1), а не на 0.0.0.0
  • Лимиты запросов: Используй limit_request_* параметры для защиты от больших запросов
python
# Безопасная конфигурация
# В gunicorn.conf.py

# Биндинг только на localhost
bind = "127.0.0.1:8000"

# Лимиты для защиты от DoS
limit_request_line = 4096
limit_request_fields = 100
limit_request_field_size = 8190

# Запуск от непривилегированного пользователя
# (указывается в systemd сервисе или при запуске)
# user = "www-data"
# group = "www-data"

Чеклист production-развертывания

  • Настроен конфигурационный файл gunicorn.conf.py
  • Оптимальное количество и тип воркеров
  • Настроен systemd сервис для автозапуска
  • Nginx настроен как reverse proxy
  • Статические файлы обслуживаются Nginx
  • Настроено логирование в файлы
  • Реализован мониторинг (метрики, здоровье)
  • Настроены параметры безопасности

Настройка Gunicorn — это баланс между производительностью, стабильностью и потреблением ресурсов. Начни с базовой конфигурации, мониторь метрики (CPU, память, response time) и постепенно оптимизируй под специфику твоего приложения. Помни: идеальной конфигурации для всех не существует — то, что работает для I/O-bound Flask-приложения, не подойдет для CPU-intensive Django-проекта.

Поделиться:
Сохранить гайд? В закладки браузера