Как реализовать простейшее WSGI приложение и открыть к нему доступ через uWSGI

Напишем, пожалуй, самое простое приложение, реализующее протокол WSGi, а также установим WSGI сервер под названием uWSGI, который будет запускать наше приложение. Я это проделаю в Linux, для иных операционных систем действия аналогичные за исключением активации виртуального окружения.

Создаем директорию и создаем в ней виртуальное окружение для python;

user@vm:~/Desktop$ mkdir venv && python3 -m venv ./venv/

Активируем созданное виртуальное окружение.

user@vm:~/Desktop$ source venv/bin/activate

В случае успеха, командная строка должна измениться:

(venv) user@vm:~/Desktop$

Теперь будут использоваться python и pip из этого виртуального окружения.

Создаем директорию для проекта, файл-приложение в ней и сразу переходим в эту директорию.

(venv) user@vm:~/Desktop$ mkdir my_server && touch my_server/app.py && cd my_server

Каким угодно образом помещаем в файл-приложение исключительно следующий код:

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    yield b'Привет, читатель!\n'

Установим uWSGI, представляющий собой сервер приложений.

(venv) user@vm:~/Desktop/my_server$ pip install uwsgi

Теперь можно запускать.

(venv) user@vm:~/Desktop/my_server$ uwsgi --http :9090 --wsgi-file app.py

Приведенная команда запускает uWSGI на порту 9090, а в качестве приложения, которое будет обрабатывать пользовательские запросы, будет использоваться ранее созданный app.py

Можно удостовериться в работоспособности этого всего с помощью браузера, не закрывая консоль, а значит, не прекращая исполнения uWSGI сервера, заходим на localhost:9090. Нас встречает html страница.

А дальше остается лишь чуть попрограммировать и можно будет мемы отдавать клиентам.

Можно возвращать и полноценный html файл. Делается это следующим образом, первым делом создается файл html, например, рядом с приложением app.py:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML-документ</title>
</head>
<body>
    <h1>Привет, читатель!</h1>
    <h2>Это уже полноценный html.</h2>
</body>
</html>

Перезапускаем uWSGI уже известной командой. И заходим на уже озвученный адрес localhost:9090.

Замена встроенного сервера в Django на uWSGI

В двух словах: никто не использует в production сервер приложений, встроенный в django поскольку он медленный, он предназначен для нужд разработчика, а не для обеспечения работы с тысячами подключений.

В общем- то, нужно раздобыть django приложение, поэтому устанавливаем в виртуальное окружение django.

(venv) user@vm:~/Desktop$ pip install django

Создаем папку для проекта.

(venv) user@vm:~/Desktop$ mkdir django_proj

Создаем django проект внутри директории.

(venv) user@vm:~/Desktop$ django-admin startproject project django_proj/

Если запустить проект сейчас, он запустится на встроенном в django WSGI-сервере.

(venv) user@vm:~/Desktop$ django_proj/manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
...

Существует несколько способов запуска проекта на uWSGI. Можно запустить проект через ini файл, можно использовать параметры по- умолчанию и произвести запуск одной командой.

(venv) user@vm:~/Desktop$ cd django_proj/ && uwsgi --module=project.wsgi --http :8001

Все, можно удостовериться, что приложение работает, обратившись к порту 8001 по http. В случае, если веб-сервер отдает страницу с текстом “Internal server error”, проблема скорее всего заключается в том, что uwsgi у вас проблема с путями. Попробуйте переместиться в папку с проектом и запускать uwsgi от туда, или же применяйте аргумент chdir:

uwsgi --chdir=/path/to/your/project ...

Конфигурирование uWSGI для работы в режиме production

Для работы в “боевом” режиме способ, описанный выше не до конца подходит, ему не достает гибкости. Можно было бы добавить аргументов команде запуска, но это не серьезный подход, в конце концов, её надо было бы где- то хранить!

Вместо этого создадим конфигурационный файл для uWSGI в корне django-проекта.

(venv) user@vm:~/Desktop/django_proj$ touch uwsgi.ini

Опишем +- классическую конфигурацию uWSGI в этом файле.

[uwsgi]
# путь до wsgi-файла, сгенерированного Django
wsgi-file = project/wsgi.py

strict = true  # предотвращает запуск сервера, если он неправильно настроен
socket = :8000  # порт, на котором принимаются запросы пользователей
protocol = http

# запустить мастер-процесс для управления дочерними процессами
master = true

# завершить все дочерние процессы
no-orphans = true

# остановить сервер при получении сигнала SIGTERM
die-on-term = true

# ленивая инициализация приложения
# это позволяет запускать сервер быстрее
# первый запрос, полученный процессом, будет работать медленно
#так как приложение будет инициализироваться.
lazy-apps = true

# количество процессов, создаваемое мастер-процессом
# рекомендуется поставить число, не превышающее количество доступных ядер процессора
processes = 4

# количество потоков, используемых каждым процессом
# каждый запрос от пользователя обрабатывается в отдельном потоке
# с помощью этих настроек можно установить максимальное количество обрабатываемых запросов
# в этой конфигурации сервер сможет обработать 32 запроса одновременно
# это число получили, умножив количество процессов на количество потоков
threads = 8

# по умолчанию uWSGI не инициирует GIL, поэтому потоки не будут работать внутри приложения
enable-threads = true

# через какое количество запросов перезапустить воркер
# это полезно для профилактики утечек памяти
max-requests = 500

# принудительно перезагрузить воркер, если он превысит порог по потребляемой памяти
reload-on-rss = 1024

# как долго ждать обработки текущих запросов воркером до принудительной перезагрузки
worker-reload-mercy = 60

# через сколько секунд принудительно завершить запрос от пользователя
harakiri = 60
harakiri-verbose = true

# очистить временные файлы и UNIX-сокеты, используемые сервером
vacuum = true

# прежде чем передать запрос приложению
# uWSGI считает в памяти его содержимое
post-buffering = 1048576

# размер буфера для чтения HTTP-заголовков
buffer-size = 65535

Все, полетели. Запуск производится через передачу приложению uwsgi созданного ini-файла.

(venv) user@vm:~/Desktop/django_proj$ uwsgi --ini uwsgi.ini