← Назад к вопросам

Зачем нужен wsgi?

1.7 Middle🔥 261 комментариев
#FastAPI и Flask#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Зачем нужен WSGI

WSGI (Web Server Gateway Interface) — это стандартный интерфейс между веб-сервером (nginx, Apache) и Python приложением (Django, Flask). Давайте разберёмся, почему это нужно.

Проблема

Без WSGI: прямая связь не работает

Браузер → Nginx (на C) → ??? → Python приложение
                          ↓
                    Несовместимо!
                    Nginx не понимает Python

Nginx написан на C и не может напрямую выполнять Python код. Нужен переводчик.

С WSGI: стандартный интерфейс

Браузер → Nginx (на C) → WSGI сервер (Gunicorn) → Python приложение (Flask, Django)
                         ↓
                    Переводчик
                    Преобразует HTTP в вызов функции

Что такое WSGI

WSGI — это простой интерфейс (конвенция), которую должно реализовать Python приложение:

# WSGI приложение — это просто функция!
def application(environ, start_response):
    """
    environ: словарь с информацией о запросе
    start_response: функция для отправки ответа
    """
    status = '200 OK'
    response_headers = [('Content-Type', 'text/plain')]
    start_response(status, response_headers)
    return [b'Hello, World!']

# Вот и всё! Это WSGI приложение.

WSGI сервер (Gunicorn, uWSGI) вызывает эту функцию для каждого HTTP запроса.

Как это работает

Шаг 1: Браузер отправляет HTTP запрос

GET /api/users HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0

Шаг 2: Nginx получает запрос

Nginx работает как reverse proxy и отправляет запрос на Gunicorn (WSGI сервер):

# Nginx не обрабатывает — просто проксирует
location / {
    proxy_pass http://127.0.0.1:8000;  # Отправляет Gunicorn'у
}

Шаг 3: Gunicorn преобразует в WSGI вызов

# Gunicorn создаёт environ (словарь)
environ = {
    'REQUEST_METHOD': 'GET',
    'PATH_INFO': '/api/users',
    'SERVER_NAME': 'example.com',
    'SERVER_PORT': '80',
    'wsgi.url_scheme': 'http',
    'wsgi.input': <input stream>,
    # ... ещё 20 параметров
}

# И вызывает функцию
response = application(environ, start_response)

Шаг 4: Python приложение обрабатывает

def application(environ, start_response):
    path = environ['PATH_INFO']
    
    if path == '/api/users':
        users = get_users()  # Получить пользователей
        body = json.dumps(users).encode()
        
        start_response('200 OK', [('Content-Type', 'application/json')])
        return [body]
    
    start_response('404 Not Found', [])
    return [b'Not Found']

Шаг 5: Gunicorn отправляет ответ обратно

HTTP/1.1 200 OK
Content-Type: application/json

[{"id": 1, "name": "John"}]

Практический пример: Flask WSGI приложение

Как работает Flask внутри

from flask import Flask

app = Flask(__name__)

@app.route('/api/users')
def get_users():
    return {'users': [{'id': 1, 'name': 'John'}]}

if __name__ == '__main__':
    app.run()

Flask это WSGI приложение

Под капотом Flask выглядит так:

class Flask:
    def __call__(self, environ, start_response):
        """Это WSGI функция!"""
        request = Request(environ)
        response = self.dispatch_request(request)
        return response(environ, start_response)
    
    def dispatch_request(self, request):
        # Маршрутизация
        # Поиск нужного обработчика
        # Вызов обработчика
        pass

# Flask объект — это WSGI приложение
application = Flask(__name__)

WSGI серверы

Gunicorn (самый популярный)

# Запуск приложения через Gunicorn
gunicorn -w 4 -b 0.0.0.0:8000 myapp:app

# -w 4: 4 worker процесса (параллельно обрабатывают запросы)
# -b 0.0.0.0:8000: слушает на порту 8000
# myapp:app: модуль myapp, объект app

uWSGI (более тяжёлый, но мощнее)

uwsgi --http :8000 --wsgi-file myapp.py --callable app --processes 4

Waitress (pure Python)

waitress-serve --port=8000 myapp:app

Deployment архитектура

┌──────────────┐
│   Browser    │
└──────┬───────┘
       │ HTTP
       ↓
┌──────────────────┐
│     Nginx        │  (reverse proxy, статика, SSL)
│  (port 80/443)   │  на C, очень быстро
└──────┬───────────┘
       │ Proxies к localhost:8000
       ↓
┌─────────────────────────────────────────────┐
│            Gunicorn (WSGI сервер)          │
│ ┌─────────┬─────────┬─────────┬─────────┐  │
│ │ Worker1 │ Worker2 │ Worker3 │ Worker4 │  │  4 процесса
│ │ Python  │ Python  │ Python  │ Python  │  │
│ └─────────┴─────────┴─────────┴─────────┘  │
└─────────────────────────────────────────────┘
       ↓ Каждый обрабатывает запросы
┌──────────────────────────────────────────────┐
│   Python приложение (Flask, Django)         │
│   - Маршрутизация                          │
│   - Обработка бизнес-логики                │
│   - Работа с БД                            │
└──────────────────────────────────────────────┘

WSGI в Docker

FROM python:3.11

WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

# Запускаем приложение через Gunicorn (WSGI сервер)
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", "app:app"]
# docker-compose.yml
services:
  app:
    build: .
    ports:
      - "8000:8000"
  
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - app

WSGI vs ASGI

WSGI (синхронный)

# Блокирующие операции
def application(environ, start_response):
    # Ждём БД
    user = db.query(User).first()  # Блокирует!
    
    # Ждём API
    response = requests.get('https://api.example.com')  # Блокирует!
    
    return [b'Success']

ASGI (асинхронный, новый стандарт)

# async/await — не блокирует
async def application(scope, receive, send):
    # Не ждём БД
    user = await async_db.query(User).first()
    
    # Не ждём API
    response = await httpx.get('https://api.example.com')
    
    await send({
        'type': 'http.response.start',
        'status': 200,
    })
КритерийWSGIASGI
СинхронизмСинхронныйАсинхронный
WebSocketsНетДа
ПроизводительностьХорошо для I/OОтлично для I/O
ПростотаПрощеСложнее
СовместимостьВезде (Django, Flask)Новые фреймворки (FastAPI)

Когда использовать WSGI

WSGI подходит:

  • Django, Flask приложения
  • Синхронный код (no async)
  • Традиционные веб-сервисы
  • Простые CRUD приложения

WSGI не подходит:

  • WebSockets требуются
  • Нужен async/await
  • Real-time приложения
  • В этом случае используй ASGI (FastAPI, Starlette)

Вывод

WSGI нужен для:

  1. Стандартизации — Python приложения и веб-серверы могут работать вместе
  2. Separation of concerns — Nginx отвечает за HTTP, Gunicorn за WSGI, Flask за бизнес-логику
  3. Масштабируемости — Gunicorn создаёт несколько worker процессов для обработки параллельных запросов
  4. Независимости — Можешь менять WSGI сервер без изменения приложения

WWSGI — это просто договор между веб-сервером и Python приложением. Благодаря этому договору всё работает вместе.

Зачем нужен wsgi? | PrepBro