Данное руководство поможет настроить простое приложение WSGI, обслуживаемое uWSGI. Веб-сервер Nginx используется в качестве обратного прокси-сервера для более надёжного соединения.
Примечание: Все компоненты установлены на сервер Ubuntu 14.04.
Основные понятия и подходы
Прежде чем приступить к работе, нужно разобраться с основными терминами и понятиями. Следующие три термина на первый взгляд кажутся взаимозаменяемыми, но на самом деле они совсем разные:
- WSGI: спецификация Python, которая определяет стандартный интерфейс для взаимодействия приложения/фреймворка с сервером приложений/веб-сервером. Её цель – упростить и стандартизировать взаимодействие этих компонентов. По сути, WSGI определяет интерфейс API, который можно использовать с другими протоколами.
- uWSGI: сервер приложений, который обеспечивает полноценную платформу для разработки и развертывания веб-приложений и сервисов. Этот сервер приложений может обрабатывать приложения, написанные на разных языках. Он взаимодействует с приложением согласно спецификации WSGI. Он может взаимодействовать с другими веб-серверами при помощи различных протоколов. Этот компонент трансформирует запросы стандартного веб-сервера в формат, который может обработать приложение.
- uwsgi: быстрый бинарный протокол, который реализуется сервером uWSGI для взаимодействия с другими полнофункциональными протоколами. Это wire протокол, а не транспортный протокол. Он лучше всего подходит для взаимодействия с веб-серверами, которые проксируют запросы для uWSGI.
Требования к приложениям WSGI
WSGI определяет интерфейс между веб-сервером и приложением. В данном контексте веб-сервером является uWSGI, который отвечает за передачу запросов клиента приложению в понятном формате. Это упрощает взаимодействие и создаёт слабосвязанные компоненты, которые можно легко заменить или удалить.
Веб-сервер (uWSGI) должен иметь возможность отправлять запросы приложению. Callable (или точка входа)– псевдотип данных, «нечто, что можно вызвать как функцию». Ожидаемым параметром является словарь с переменными окружения и точка входа веб-сервера.
В ответ приложение отправляет итератор, при помощи которого будет сгенерировано тело запроса клиента. Также оно вызовет точку входа веб-сервера, которую оно получило в виде параметра. Первым параметром при извлечении точки входа будет код состояния HTTP, а вторым – список наборов, каждый из которых определяет заголовок ответа и значение, которое нужно вернуть клиенту.
Установка компонентов
Для начала нужно установить все необходимые программы на сервер Ubuntu 14.04. Для этого можно использовать apt и pip.
Обновите индекс пакетов и установите библиотеку разработки Python, pip (пакетный менеджер Python) и веб-сервер Nginx.
sudo apt-get update
sudo apt-get install python-dev python-pip nginx
После завершения установки вы получите доступ к пакетному менеджеру pip. С его помощью можно установить пакет virtualenv, который позволяет изолировать окружение приложения Python от остальных программ системы.
sudo pip install virtualenv
После этого можно создать общую структуру приложения. Создайте виртуальное окружение и установите в него сервер приложений uWSGI.
Создание каталога и виртуальной среды приложения
Теперь создайте папку для приложения. В ней вы сможете развернуть виртуальную среду и хранить точку входа WSGI.
mkdir ~/myapp/
Откройте этот каталог:
cd ~/myapp
Создайте виртуальную среду с помощью команды virtualenv (для простоты в руководстве она называется myappenv)
virtualenv myappenv
Теперь в каталоге myappenv развёрнуто новое окружение Python. Включите его:
source myappenv/bin/activate
После этого командная строка изменится. Это значит, что виртуальная среда активна:
(myappenv)username@host:~/my_app$
Чтобы покинуть виртуальную среду, используйте команду:
deactivate
Примечание: Если вы вышли из виртуальной среды только что, вернитесь в неё.
Когда виртуальная среда включена, все устанавливаемые приложения Python будут помещены в иерархию этого каталога. Они не смогут повлиять на общесистемные приложения Python. Теперь можно установить сервер uWSGI с помощью pip. Его пакет называется uwsgi (однако не следует путать пакет сервера uWSGI с протоколом uwsgi).
pip install uwsgi
Чтобы убедиться, что установка прошла успешно, запросите версию:
uwsgi --version
Команда должна вернуть версию сервера uWSGI.
Создание приложения WSGI
Теперь нужно создать простое приложение WSGI согласно спецификации WSGI. Это приложение должно состоять из таких компонентов:
- Интерфейс для callable.
- Точка входа должна в качестве параметра содержать словарь, в котором хранятся переменные в виде пар «ключ-значение», и точку входа сервера uWSGI.
- Точка входа должна возвращать итератор, что сгенерирует тело для отправки клиенту.
- Приложение должно вызывать точку входа веб-сервера с состоянием HTTP и заголовками запросов.
Запишите приложение в файл wsgi.py:
nano ~/myapp/wsgi.py
В этом файле будет находиться простое приложение, созданное согласно WSGI.
Важно! Вносите код, учитывая отступы.
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return ["<h1 style='color:blue'>Hello There!</h1>"]
Это полный код простого приложения WSGI. По умолчанию uWSGI будет искать точку входа по имени application, потому функция названа именно так. Как видите, она берёт два параметра.
Первый параметр называется environ и задаёт словарь переменных. Второй параметр называется start_response и сообщает точке входа веб-сервера uWSGI имя приложения.
Приложение будет выполнять два действия. Во-первых, оно вызовет точку входа, полученную с кодом состояния HTTP и заголовками. В таком случае отправляется ответ 200 ОК, а text/html получает заголовок Content-Type.
Во-вторых, приложение будет возвращать итератор в качестве тела запроса. В данном приложении используется одна строка HTML. Строки тоже относятся к итератору, но в списке uWSGI может обрабатывать целую строку при помощи одного итератора.
Такой файл, скорее всего, будет использоваться как ссылка на остальной код приложения. к примеру, Django-проекты включают файл wsgi.py по умолчанию. Он переводит запросы веб-сервера uWSGI в понятный приложению формат. Упрощенный интерфейс WSGI остаётся таким независимо от сложности самого кода приложения.
Сохраните и закройте файл.
Чтобы протестировать код, запустите uWSGI. Сервер будет использовать HTTP и прослушивать порт 8080. Передайте серверу название сценария:
uwsgi --socket 0.0.0.0:8080 --protocol=http -w wsgi
Теперь посетите в браузере IP-адрес или доменное имя, задав порт 8080. На экране появится фраза:
Hello There!
Остановите сервер, нажав CTRL-C.
Теперь приложение готово. Отключите виртуальную среду:
deactivate
Конфигурационный файл uWSGI
В вышеприведённом примере вы вручную запустили сервер uWSGI и передали ему несколько параметров. Чтобы не делать это вручную всегда, создайте конфигурационный файл.
uWSGI может читать конфигурации в разных форматах; в руководстве для простоты используется формат .ini. Создайте файл myapp.ini:
nano ~/myapp/myapp.ini
В этом файле нужно создать раздел кода [uwsgi]. В нём будут храниться все конфигурации. Задайте настройки самого приложения. Сервер uWSGI должен знать о местонахождении точки входа приложения.
[uwsgi]
module = wsgi:application
Начальный процесс uwsgi должен быть ведущим (master) и порождать множество рабочих процессов (в данном примере 5).
[uwsgi]
module = wsgi:application
master = true
processes = 5
Теперь нужно изменить протокол, с помощью которого uWSGI взаимодействует с другими компонентами. Во время тестирования был установлен протокол –protocol=http, чтобы приложение можно было просмотреть в браузере. Однако в в дальнейшем будет настроен обратный прокси-сервер Nginx, который реализует механизм проксирования uwsgi (быстрый бинарный протокол, с помощью которого uWSGI взаимодействует с другими серверами). Протокол uwsgi является протоколом uWSGI по умолчанию, потому достаточно просто не задавать протокол, чтобы сервер использовал uwsgi.
Поскольку этот конфигурационный файл должен поддерживать взаимодействие с Nginx, замените стандартный порт сокетом Unix. Это более быстрый и безопасный вариант. Сокет будет создан в текущем каталоге (в руководстве он будет называться myapp.sock). Измените права доступа к нему, указав 664, чтобы веб-сервер Nginx имел право на редактирование. Добавьте опцию vacuum, которая удалит сокет сразу после остановки процесса:
[uwsgi]
module = wsgi:application
master = true
processes = 5
socket = myapp.sock
chmod-socket = 664
vacuum = true
Осталось добавить последнюю опцию, которая нужна для поддержки файла Upstart. Upstart и uWSGI по-разному воспринимают сигнал SIGTERM. Чтобы устранить эту проблему, просто добавьте опцию die-on-term.
[uwsgi]
module = wsgi:application
master = true
processes = 5
socket = myapp.sock
chmod-socket = 664
vacuum = true
die-on-term = true
Сохраните и закройте файл.
Создание файла Upstart
Теперь можно настроить автозапуск uWSGI во время загрузки сервера. Поместите его в каталог /etc/init, который проверяет система Upstart (в руководстве файл называется myapp.conf).
sudo nano /etc/init/myapp.conf
Добавьте описание сервиса и установите уровни выполнения. Уровни выполнения стандартного пользователя – 2-5.
Если приложение перейдет на уровень, который не входит в этот диапазон, Upstart остановит его.
description "uWSGI instance to serve myapp"
start on runlevel [2345]
stop on runlevel [!2345]
Теперь установите пользователя и группу, с помощью которых будет запущен процесс. В качестве группы можно указать www-data, чтобы сервер Nginx имел доступ к приложению.
description "uWSGI instance to serve myapp"
start on runlevel [2345]
stop on runlevel [!2345]
setuid demo
setgid www-data
После этого нужно добавить команды для запуска uWSGI. Вы можете предоставить полный путь к uWSGI, а можете включить виртуальную среду.
После этого добавьте блок script. В нем можно открыть каталог приложения, включить виртуальную среду (вместо символа . используйте source) и запустите uWSGI с помощью файла .ini.
description "uWSGI instance to serve myapp"
start on runlevel [2345]
stop on runlevel [!2345]
setuid demo
setgid www-data
script
cd /home/demo/myapp
. myappenv/bin/activate
uwsgi --ini myapp.ini
end script
Сценарий готов. Сохраните и закройте его.
Запустите сервис:
sudo start myapp
Чтобы убедиться, что сервер запущен, введите:
ps aux | grep myapp
demo 14618 0.0 0.5 35868 5996 ? S 15:02 0:00 uwsgi --ini myapp.ini
demo 14619 0.0 0.5 42680 5532 ? S 15:02 0:00 uwsgi --ini myapp.ini
demo 14620 0.0 0.5 42680 5532 ? S 15:02 0:00 uwsgi --ini myapp.ini
demo 14621 0.0 0.5 42680 5532 ? S 15:02 0:00 uwsgi --ini myapp.ini
demo 14622 0.0 0.5 42680 5532 ? S 15:02 0:00 uwsgi --ini myapp.ini
demo 14623 0.0 0.5 42680 5532 ? S 15:02 0:00 uwsgi --ini myapp.ini
demo 15520 0.0 0.0 11740 936 pts/0 S+ 15:53 0:00 grep --color=auto myapp
Теперь сервис будет автоматически загружаться вместе с системой. Чтобы остановить сервис, введите:
sudo stop myapp
Nginx как обратный прокси-сервер для uWSGI
Итак, теперь приложение WSGI работает и поддерживается сервером uWSGI. Также сервис запускается автоматически при помощи Upstart. Процесс uWSGI прослушивает сокет и взаимодействует с протоколом uwsgi.
Теперь нужно настроить Nginx как обратный прокси-сервер. Nginx может проксировать запросы при помощи протокола uwsgi для взаимодействия с uWSGI. Этот протокол быстрее, чем HTTP.
Настройка Nginx очень проста. Нужно только создать новый файл в каталоге sites-available в иерархии Nginx (имя файла должно совпадать с именем приложения, потому в руководстве файл называется myapp).
sudo nano /etc/nginx/sites-available/myapp
В этом файле нужно задать номер порта и доменное имя, к которому относится данный блок server. В данном случае используется стандартный порт 80.
server {
listen 80;
server_name server_domain_or_IP;
}
Чтобы приложение WSGI могло отправлять все запросы на этот домен или IP, нужно создать блок location для запросов, которые начинаются с / (это соответствует всем запросам). Добавьте в него директиву include, чтобы внести ряд параметров по умолчанию из конфигурационного каталога Nginx. Этот файл называется uwsgi_params. После этого нужно передать трафик приложению uWSGI через протокол uwsgi. Для этого используется сокет unix.
server {
listen 80;
server_name server_domain_or_IP;
location / {
include uwsgi_params;
uwsgi_pass unix:/home/demo/myapp/myapp.sock;
}
}
Этих настроек достаточно для поддержки простого приложения. Сложным приложениям нужна более тонкая настройка (например, можно определить количество upstream-серверов uWSGI вне этого блока, добавить больше параметров uWSGI, настроить обработку статических файлов Nginx и передавать uWSGI только динамические запросы). В данном случае такие сложные функции не нужны. Просто сохраните и закройте файл.
Чтобы привести новые параметры в исполнение, создайте символьную ссылку на каталог sites-enabled.
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled
Проверьте конфигурационный файл на наличие ошибок:
sudo service nginx configtest
Если в файле нет ошибок, перезапустите веб-сервер:
sudo service nginx restart
После этого откройте в браузере доменное имя или IP (без номера порта). На экране появится:
Hello There!
Заключение
Теперь у вас есть полностью рабочее простое приложение WSGI. Его можно использовать как шаблон для создания более сложного приложения.
uWSGI может управлять несколькими приложениями, для этого используется так называемый «emperor mode». Вы можете расширить настройки Nginx, добавив балансировку нагрузки. Все компоненты достаточно гибкие, их можно настроить согласно требованиям вашего приложения.