alvelin 17.06.2010 11:14
Python — Nginx-uWSGI-Django
Начнем с самого начала:uWSGI - это еще один WSGI сервер, позволяющий запускать приложения, написанные на Python (на самом деле, не только на нем).
Официальный сайт расположен по адресу - http://projects.unbit.it/uwsgi.
Впечатляющие (особенно для любителей сферически-вакуумных коней) тесты производительности можно найти здесь - http://nichol.as/benchmark-of-python-web-servers.
Впрочем, в результатах нет ничего удивительного - uWSGI написан на чистом С и, очевидно, написан хорошо.
Полагаю, с предисловием на этом можно закончить.
В качестве практической части предлагаю описание установки и запуска связки uWSGI+nginx+Django.
Для начала установим uWSGI:
wget http://projects.unbit.it/downloads/uwsgi-latest.tar.gz
либо:
pip install http://projects.unbit.it/downloads/uwsgi-latest.tar.gz
либо ищем в репах своего дистрибутива.
В случае с Arch-ем, это будет, естественно:
yaourt -Ss uwsgi
Разницы нет, но я предпочитаю первый способ.
С установкой штатными средствами могут возникнуть сложности - т.к. с версией nginx < 0.8.40 нам еще будут нужны файлы модуля для nginx из архива uwsgi. Установка через pip проще, но, опять же, сейчас я ее рассматривать не собираюсь.
Далее - все просто(даже слишком). Распаковываем полученный архив(если ставим из исходников,), переходим в каталог и выполняем самый заурядный:
make
либо:
make -f Makefile.Py26 - если мы собираем uWSGI под конкретную версию Python'а
либо:
python uwsgiconfig.py --build - если по каким-то причинам нет возможности добраться до make.
Зависимостей у uWSGI немного - только заголовочные файлы Python'а и libxml2.
Через пару минут все это добро скомпилируется. Можно двигаться дальше и установить nginx.
Для упрощения задачи возьмем одну из свежих текущих версий. К примеру эту - http://nginx.org/download/nginx-0.8.41.tar.gz. Последние версии(начиная 0.8.40) идут уже в комплекте с uWSGI-модулем, в случае с более ранними версиями, при компиляции необходимо будет указать обычное для установки модулей:
--add-module=$/путь/до/uwsgi/nginx
В случае с последними версиями nginx можно еще указать и:
--http-uwsgi-temp-path= /бла/бла/бла - дабы он находился за пределами каталога, в который ставится nginx
Прочии опции типичны для любой сборки nginx. Впрочем, я посоветовал бы указать еще и prefix - т.к. мы работаем помимо всех средств установки и забота о поддержании актуальности версии ляжет на наши плечи.
Сборка nginx'а так же не должна занять много времени.
Полагаю, Django у вас уже установлен и на этом моменте останавливаться не буду. Перейдем к самому интересному - настройке всего этого дела.
В первую очередь подчищаем nginx.conf - его содержание, конечно, поучительно, но нам требуется его немного изменить. Примерно до такого вида (не бесспорно, но работает):
#user nobody;
worker_processes 1;
error_log /var/log/nginx-0.8.41-error.log;
pid /tmp/nginx-0.8.41.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
userid on;
userid_expires max;
log_format main '$remote_addr - $remote_user <$time_local> '
'"$request" $status $bytes_sent $body_bytes_sent '
'"$http_referer" "$http_user_agent"'
'"$gzip_ratio" "$uid_set" "$uid_got"';
log_format download '$remote_addr - $remote_user <$time_local> '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_range" "$sent_http_content_range"';
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
output_buffers 4 32k;
postpone_output 1460;
sendfile on;
tcp_nopush on;
keepalive_timeout 75 20;
tcp_nodelay on;
gzip on;
gzip_min_length 1100;
gzip_buffers 4 32k;
#gzip_types text/plain text/html application/x-javascript text/xml text/css;
client_max_body_size 10m;
client_body_buffer_size 256k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 64k;
proxy_buffers 4 128k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
error_page 500 502 503 504 403 /403.html;
error_page 401 /401.html;
error_page 404 /404.html;
error_page 400 /400.html;
proxy_intercept_errors on;
log_not_found off;
autoindex_exact_size off;
ignore_invalid_headers on;
############################VIRTUAL SERVERS#####################################
include vhosts/vhost-uwsgi.conf;
################################################################################
}
Далее создаем папку vhosts, а в ней наш vhost-uwsgi.conf с примерно следующим содержанием:
upstream djangoserv {
server 127.0.0.1:8012;
}
server {
listen 80;
server_name ваш будущий сайт;
access_log /var/log/nginx-0.8.41-access.log;
error_log /var/log/nginx-0.8.41-error.log;
location /mysite/ {
root /путь/до/вашего/проекта/на/Django;
}
location ^~ /media/ {
root /путь/до/дистрибутива/Django/django/contrib/admin/;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mov) {
expires 30d;
}
location / {
# host and port to uwgi server
uwsgi_pass 127.0.0.1:8012;
include uwsgi_params;
}
}
server 127.0.0.1:8012;
}
server {
listen 80;
server_name ваш будущий сайт;
access_log /var/log/nginx-0.8.41-access.log;
error_log /var/log/nginx-0.8.41-error.log;
location /mysite/ {
root /путь/до/вашего/проекта/на/Django;
}
location ^~ /media/ {
root /путь/до/дистрибутива/Django/django/contrib/admin/;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mov) {
expires 30d;
}
location / {
# host and port to uwgi server
uwsgi_pass 127.0.0.1:8012;
include uwsgi_params;
}
}
Естественно, что тут все очень приблизительно. Отдельно стоит отметить location ^~ /media/, позволяющий отдавать статику админки Django. Тут могут возникнуть нек-рые сложности.
Далее - копируем в в ту же папку, где лежит nginx.conf uwsgi_params из каталога uwsgi/nginx.
Уфф... теперь можно переходить к завершающей стадии.
Переходим в папку с нашим Django-проектом (путь к нему мы уже указали в нашем vhost-uwsgi.conf).
Там создаем файлик django_wsgi.py примерно следующего содержания:
import os
os.environ<'DJANGO_SETTINGS_MODULE'> = 'settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
Со строчкой
os.environ<'DJANGO_SETTINGS_MODULE'> = 'settings', возможно, придется пошаманить - добавить или убрать название вашего проекта. Так же, как, впрочем и с ROOT_URLCONF в settings.py, приведя его к:
ROOT_URLCONF = 'urls'
И, наконец, последний рывок - запуск. Как запустить nginx, думаю, объяснять никому не надо. Запуск связки uWSGI-Django чуть более затейлив. В принципе, это можно сделать одной коммандной строкой, но как верно замечают создатели uWSGI, она получится чертовски длинной.
Поэтому мы создадим в папке нашего проекта файл django.xml с примерно следующим содержанием:
1 |
<uwsgi>
|
Теперь у нас все готово к запуску. Набираем в коммандной строке:
путь/до/бинарника/uwsgi -x путь/до/django.xml
и, наконец, наслаждаемся результатами наших трудов.
Если что пошло не так, то проверяем конфиги/ругаем автора за допущенные в описании ошибки. Впрочем, в моем случае все работает.
Ага.
А могут и не возникнуть. Примерный конифиг =! готовый конфиг
А могут и не возникнуть. Примерный конифиг =! готовый конфиг
Все очень сложно.
Я использую CherryPy как WSGI сервер + nginx. По бенчмаркам по ссылке, приведенной вами, он мало чем уступает uWSGI.
CherryPy запускаю с пмомощью django_cpserver (добавляется команда manage.py runcpserver)
Nginx на взаимодействие с wsgi конфигурирую через proxy_pass.
И никаких XML конфигов, ручных прописываний django settings module и прочего кошмара.
Я использую CherryPy как WSGI сервер + nginx. По бенчмаркам по ссылке, приведенной вами, он мало чем уступает uWSGI.
CherryPy запускаю с пмомощью django_cpserver (добавляется команда manage.py runcpserver)
Nginx на взаимодействие с wsgi конфигурирую через proxy_pass.
И никаких XML конфигов, ручных прописываний django settings module и прочего кошмара.
Кстати, может быть опишите - более-менее подробно, - свой опыт запуска-настройки связки CherryPy+nginx?
Если честно, то я не спорю, что на вкус и цвет все фломастеры разные... CherryPy таит свои проблемы (спрос с google'a).Gunicorn ссылкаможет тоже показать неплохие результаты, но... речь шла именно о uWSGI. Если есть желание, можем разработать собственный - не столь сферический - бенчмарк. Одному - делать этого не охота,но за компанию... В целом - мериться только скоростью просто глупо. Я как-то с ходу понимаю, то нужно для uWSGI, но, вместе с тем, понятно, что время разработчика может стоить дороже, чем то, что он потратит на разборки с новым soft-сервером. На освободившуюся тыщщу долларов можно, вполне, купить более мощное железо.
все сделал сервер пашет страницы отображает но не работают css. Подскажите что прописывать в шаблонах в линках что прописать в settings.py плз.
Админка вероятно не подхватилась. Смотрите в конфиге Nginx'а. Полагаю, проблема где-то здесь:
location ^~ /media/ {
root /путь/до/дистрибутива/Django/django/contrib/admin/;
}
location ^~ /media/ {
root /путь/до/дистрибутива/Django/django/contrib/admin/;
}
expires 30d;
}
типичное заблуждение по поводу отдачи статики
могут возникнуть проблемы с динамическим генерированием картинок, js, css, пдф и т.п. и т.д.
поэтому лучше юзать директиву try_files
например
location / {
try_files $uri $uri/ @django;
}
location @django {
uwsgi_pass 127.0.0.1:8012;
include uwsgi_params;
}