5 April 2011

Nginx + uWSGI + Django, один из вариантов запуска

System administration
Статья описывает один из способов развертывания Django-проектов, в связке Nginx + uWSGI на Unix-подобных операционных системах. Тестирование, а так же дальнейшая рабочая эксплуатация производилась на FreeBSD, однако на Linux процесс будет схож, за исключением некоторых незначительных моментов.

Введение


В один из дней, на месте работы возникла необходимость запуска Web-приложений написанных на Django (Python). В ходе поиска, было найдено большое количество схожих статей, описывающих запуск Django-проектов с использованием Nginx + uWSGI. Авторы рассматривали запуск конкретно одного Django-проекта, у которого был свой конфигурационный xml-файл для uWSGI-воркера(ов), а так же отдельный сокет/порт для взаимодействия с Nginx'ом. В следствие чего, при добавлении нового Django-проекта, возникнет необходимость заново производить настройку uWSGI-воркера(ов) уже для этого приложения (пускай даже копипастом, но все же). К сожалению, данный метод не универсален и при такой конфигурации нет единого, привычного FreeBSD'шнику мне средства контроля работающего демона, единой точки управления. Вследствие чего, после поисков в Internet и изучения официальной wiki uWSGI-проекта, был выработан следующий метод запуска (принципиальные отличия):
  • Единый, обобщенный конфигурационный xml-файл для uWSGI-воркера(ов);
  • Специфичные параметры, описываемые для каждого Django-проекта в конфигурационном xml-файле для uWSGI-воркера(ов) переносятся в location'ы Nginx'а и передаются uWSGI-воркеру из Nginx'а.
Каталог размещения приложений

Предполагается использование единого каталога, в котором будет развернут конгломерат Django-проектов, в моем случае это /usr/local/www. Например, содержимое каталога будет примерно следующим:
# ls -la /usr/local/www/
...
drwxr-xr-x ... app1
drwxr-xr-x ... app2
drwxr-xr-x ... appN
-rw-r--r-- ... webapp.xml


Настройка Nginx

Настройка location'ов производится исходя из принципа, один Django-проект — один location.

nginx.conf:
        location / {
                uwsgi_pass              unix:///tmp/uwsgi.sock;
                include                 uwsgi_params;

                uwsgi_param             UWSGI_SCRIPT            webapp;
                uwsgi_param             UWSGI_CHDIR             /usr/local/www/app1;
        }

        location /app2 {
                uwsgi_pass              unix:///tmp/uwsgi.sock;
                include                 uwsgi_params;

                uwsgi_param             SCRIPT_NAME             /app2;
                uwsgi_param             UWSGI_SCRIPT            webapp;
                uwsgi_param             UWSGI_CHDIR             /usr/local/www/app2;

        }

        location /appN {
                uwsgi_pass              unix:///tmp/uwsgi.sock;
                include                 uwsgi_params;

                uwsgi_param             SCRIPT_NAME             /appN;
                uwsgi_param             UWSGI_SCRIPT            webapp;
                uwsgi_param             UWSGI_CHDIR             /usr/local/www/appN;

        }

В данной конфигурации location'ов:
  • Параметр «SCRIPT_NAME /appN» соответствует параметру конфигурационного xml-файла uWSGI-воркера(ов) «
    <app mountpoint="/appN">...</app>
    » и обозначает контекст Django-проекта;
  • Параметр «UWSGI_SCRIPT webapp» соответствует параметру webapp и обозначает точку входа в Django-проект (о точке входа в приложение чуть ниже);
  • Параметр «UWSGI_CHDIR /usr/local/www/appN» соответствует параметру /usr/local/www/appN и обозначает каталог с Django-проект.
Конфигурационный файл webapp.xml

Конфигурационный xml-файл для uWSGI-воркера(ов) webapp.xml размещается в каталоге /usr/local/www.

webapp.xml:
<uwsgi>
        <socket>/tmp/uwsgi.sock</socket>
        <process>1</process>

        <master/>
        <enable-threads/>

        <uid>80</uid>
        <gid>80</gid>

        <pidfile>/var/run/uwsgi.pid</pidfile>
</uwsgi>

Точка входа в Django-проект

Важно чтоб в каталоге каждого приложения app1, app2, appN находился файл webapp, представляющий собой точку входа в Django-проект. uWSGI-воркер запускает webapp, а webapp в свою очередь запускает WSGI-обработчик в Django-проекте.

Вот так выглядит webapp для проекта app1:
# -*- coding: iso-8859-1 -*-

import sys, os
import django.core.handlers.wsgi

sys.path.insert(0, '/usr/local/www/app1')
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

application = django.core.handlers.wsgi.WSGIHandler()

Вместо заключения


На этом настройка заканчивается. Теперь, для запуска uWSGI-воркера(ов) обслуживающих все Django-проекты, достаточно выполнить следующую команду:
# uwsgi -s /tmp/uwsgi.sock -x /usr/local/www/webapp.xml

На FreeBSD запуск можно организовать более красиво нежели в Linux:
/etc/rc.conf:
uwsgi_enable=«YES»
uwsgi_flags="-x /usr/local/www/webapp.xml"

# /usr/local/etc/uwsgi start

При такой конфигурации, достаточно распаковать в рабочий каталог Django-проект, добавить шаблонный location в Nginx и сделать рестарт Nginx- и uWSGI-демонам.

Используемые литература блоги

projects.unbit.it/uwsgi/wiki/RunOnNginx
projects.unbit.it/uwsgi/wiki/Example
projects.unbit.it/uwsgi/wiki/Emperor

http://wiki.diphost.ru/Category:WSGI
blog.zacharyvoase.com/2010/03/05/django-uwsgi-nginx
www.westphahl.net/blog/2010/4/8/running-django-nginx-and-uwsgi
posterous.adambard.com/start-to-finish-serving-mysql-backed-django-w
brandonkonkle.com/blog/2010/sep/14/django-uwsgi-and-nginx
www.jeremybowers.com/blog/post/5/django-nginx-and-uwsgi-production-serving-millions-page-views
www.cherokee-project.com/doc/cookbook_uwsgi.html
Tags:nginxdjangouwsgi
Hubs: System administration
+44
32k 160
Comments 56
Top of the last 24 hours