Для интеграции Gunicorn с FastAPI необходимо настроить веб-сервер, который будет управлять процессами и обрабатывать HTTP-запросы. Gunicorn часто используется для запуска асинхронных приложений в продакшене, так как позволяет эффективно масштабировать нагрузку. Вот пошаговое руководство:
pip install fastapi gunicorn uvicornПример запуска FastAPI через Gunicorn:
gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app-w 4: Количество worker-процессов (рекомендуетсяworkers = 2 * CPU_CORES + 1).-k uvicorn.workers.UvicornWorker: Указание асинхронного worker'а для FastAPI.
gunicorn main:app \
--workers 4 \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000 \
--timeout 120Создайте файл gunicorn.conf.py:
bind = "0.0.0.0:8000"
workers = 4
worker_class = "uvicorn.workers.UvicornWorker"
timeout = 120
accesslog = "-"
errorlog = "-"
loglevel = "info"Запуск:
gunicorn -c gunicorn.conf.py main:appgunicorn main:app \
--workers 4 \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000 \
--access-logfile - \
--error-logfile - \
--timeout 120 \
--keepalive 120 \
--log-level info \
--capture-output \
--enable-lookupexport APP_MODULE=main:app
export WORKERS=4
export PORT=8000
gunicorn $APP_MODULE \
--workers $WORKERS \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:$PORTserver {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://localhost: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;
}
}Создайте файл /etc/systemd/system/fastapi.service:
[Unit]
Description=FastAPI with Gunicorn
After=network.target
[Service]
User=your_user
Group=www-data
WorkingDirectory=/path/to/your/project
ExecStart=/usr/bin/gunicorn -c /path/to/gunicorn.conf.py main:app
Restart=on-failure
KillMode=mixed
TimeoutStopSec=20
PrivateTmp=true
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now fastapi.serviceДля FastAPI (основанного на ASGI) используйте uvicorn.workers.UvicornWorker, так как стандартные worker'ы Gunicorn не поддерживают асинхронность:
gunicorn ... -k uvicorn.workers.UvicornWorker# В gunicorn.conf.py
import multiprocessing
workers = multiprocessing.cpu_count() * 2 + 1gunicorn ... \
--access-logfile /var/log/gunicorn/access.log \
--error-logfile /var/log/gunicorn/error.log \
--log-level debugСоздайте файл logging.conf:
[loggers]
keys=root,gunicorn.error,gunicorn.access
[handlers]
keys=consoleRotatingFileHandler
[formatters]
keys=json_formatter
[logger_root]
level=INFO
handlers=consoleRotatingFileHandler
[logger_gunicorn.error]
level=INFO
handlers=consoleRotatingFileHandler
qualname=gunicorn.error
propagate=0
[logger_gunicorn.access]
level=INFO
handlers=consoleRotatingFileHandler
qualname=gunicorn.access
propagate=0
[handler_consoleRotatingFileHandler]
class=logging.handlers.RotatingFileHandler
formatter=json_formatter
args=("/var/log/gunicorn/app.log", "a", 5000000, 5)
[formatter_json_formatter]
format = %(asctime)s [%(process)d] [%(levelname)s] %(message)s
datefmt = %Y-%m-%d %H:%M:%S
class = pythonjsonlogger.jsonlogger.JsonFormatterFROM python:3.9-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["gunicorn", "-c", "gunicorn.conf.py", "main:app"]version: '3.8'
services:
api:
build: .
ports:
- "8000:8000"
environment:
- WORKERS=4
depends_on:
- db# gunicorn.conf.py
bind = "0.0.0.0:8000"
workers = 8
worker_class = "uvicorn.workers.UvicornWorker"
threads = 2
timeout = 120
keepalive = 2
accesslog = "/var/log/gunicorn/access.log"
errorlog = "/var/log/gunicorn/error.log"
loglevel = "info"gunicorn main:app \
--workers 4 \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000- Для асинхронных приложений используйте
uvicorn.workers.UvicornWorker. - Избегайте
syncworker'ов (например,syncилиgevent).
--timeout: Установите разумное значение (например, 120 секунд).--preload: Загрузка приложения до запуска worker'ов (полезно для обработки сигналов).--graceful-timeout: Время ожидания завершения worker'а при перезагрузке.
- Избегайте запуска Gunicorn как root.
- Используйте Nginx для внешнего доступа и SSL-терминации.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello World"}bind = "0.0.0.0:8000"
workers = 4
worker_class = "uvicorn.workers.UvicornWorker"
accesslog = "-"
errorlog = "-"
loglevel = "info"Убедитесь, что путь к приложению указан правильно (например, main:app).
Если используется асинхронный код, обязательно используйте UvicornWorker:
gunicorn -k uvicorn.workers.UvicornWorker ...Для долгих задач увеличьте timeout:
gunicorn ... --timeout 300gunicorn main:app \
--workers $(($(nproc)*2+1)) \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000gunicorn main:app \
--workers 4 \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000 \
--reload- uvicorn: Для асинхронных worker'ов.
- gunicorn: Основной веб-сервер.
- systemd: Для управления сервисами в Linux.
Для работы с Gunicorn в FastAPI:
- Используйте
uvicorn.workers.UvicornWorkerдля асинхронности. - Настройте количество workers в зависимости от количества CPU.
- Интегрируйте с Nginx для внешнего доступа и SSL.
- Используйте systemd для автозапуска и мониторинга.
- Настройте логирование для отслеживания ошибок и производительности.
Это обеспечит стабильный и масштабируемый запуск вашего FastAPI приложения.