Публикации с меткой «nginx»

Блог django на хабрахабре

Django Framework / Nginx + uWSGI + virtualenv + Django на Debian Squeeze

Некоторое время назад озадачился поиском способа развертывания проектов Django, к которому предъявлялись два требования:
  1. Удобное управление запуском/остановкой/перезапуском нескольких проектов на одном хосте
  2. Поддержка разных виртуальных сред для разных проектов

По второму пункту мой выбор склонился в пользу Nginx + uWSGI. По первому же, из рассмотренных мною вариантов больше всего понравились обвязки для uWSGI в Debian.

Блог django на хабрахабре

Django Framework / Мониторим Django проекты в top'e

В этой статье я опишу как настроить Django так, что б на сервере в top'е можно было видеть нагрузку на сервер от каждого из Django-проектов.

Блог django на хабрахабре

Django Framework / Плавный перезапуск FastCGI-процессов — django_graceful

Из всех способов деплоинга django-проектов мой любимый — FastCGI. Он поддерживается большинством веб-серверов, позволяет внятно разграничить права доступа и имеет массу других преимуществ.

Однако в django его реализация не лишена недостатков. Чтобы запустить FastCGI-сервер нужно выполнить «./manage.py runfcgi» с немаленьким количеством параметров, которые если и можно запомнить, то точно не захочется писать каждый раз руками. А если это происходит в контексте обновления кода проекта на боевом сервере, то команд становится ещё больше. Приходится писать различные wrapper-ы для запуска и перезапуска, которые засоряют проект.

CAN HAZ SOM BLOG?

Django + nginx: не загружаюцо файлы?

Никогда бы не подумал, что:
WSGIServer: missing FastCGI param SERVER_PORT required by WSGI!
WSGIServer: missing FastCGI param SERVER_PROTOCOL required by WSGI!" while reading upstream, client: xx.xx.xxx.xx, server: xxx.xxx.xxx.xxx, request: "POST /profiles/change_data/ HTTP/1.1", upstream: "fastcgi://unix:/home/constellation/front.sock:", host: "xxx.xxx.xxx.xxx:xxxx", referrer: "http://xxx.xxx.xxx.xxx:xxxx/profiles/change_data/"
может быть причиной фейла при заливе файлов через форму.

Такие дела.


Даёшь Django в народные массы!

О портах в nginx

Потребовалось развернуть 2 разных инстанса сервера на джанго на одном и том же хосте, но на разных портах.
Django крутится в mod_wsgi за nginx.
На первый взгляд всё выглядело нормально, но сюрприз образовался, когда попытался я зайти в админку: после логина следовал редирект на сайт с дефолтным 80-м портом (хотя в админку я залезал по другому порту).
Вскрытие (спустя более часа разбирательств) показало, что во всём виноват проксирующий nginx, в котором была прописана директива "proxy_set_header Host $host:$server_port;". Всё легко разрешилось добавлением порта - "proxy_set_header Host $server_port;".

Веб мозги

Запуск django сайта через nginx + superfcgi

Я вчера перевёл все свои сайты на связку nginx + fastcgi-демон. Раньше они работали на связке nginx + apache/mod_wsgi. Даже не знаю, зачем я это сделал. Да и какая разница :o) Я сейчас просто опишу как соединять nginx с fastcgi-django-демонами через библиотеку superfcgi и надеюсь, кому-нибудь это будет полезно.

Так вот, для начала нада поставить superfcgi библиотеку. Кстати, её автор barbuza. Ставится банально: pip install superfcgi. Только не забудьте зависимости поставить предварительно. В debian надо ставить такие пакеты: gcc, python2.5-dev (если у вас 2.5 python), libfcgi-dev. Ещё надо multiprocessing либу поставить в случае python2.5, правда, Виктор говорит, что она уже автоматически ставиться. Но, если что, имейте в виду.

После установки superfcgi надо прописать ‘superfcgi’ в settings.INSTALLED_APPS. Это сделает доступной команду manage.py runserupfcgi, с помощью которой можно запустить процесс, который позволит общаться с nginx через fastcgi-интерфейс.

Проблема в том, что надо как-то контролировать этот процесс: уметь его останавливать, например. Команда manage.py runsuperfcgi этого не умеет, поэтому я использую дополнительный bash скрипт. Пощупать его можно тут: http://bitbucket.org/lorien/spawn/src/tip/spawn.sh

У меня для каждого сайта есть свой маленький spawn.sh, в котором я задаю одну переменную $SITE и затем делаю include главного spawn.sh. Например, для запуска веб-мозгов у меня такой скрипт:

На всякий случай, если вдруг сайт упадёт или будет сделан rebot сервера у меня в кроне каждую минуту стартуются все сайты. Тупо, да, зато работает :D Конечно, если сайт уже запущен, то копия не запускается, в spawn.sh учтёт этот момент. Каждую минуту я пытаюсь запустить все сайты таким скриптом:

Кроме django-сайтов я запустил через superfcgi также один trac-проект. Для этого я сделал следующее, создал в директории проекта файл trac_wsgi.py

import os

os.environ['TRAC_ENV'] = '/web/pybb.org'
os.environ['PYTHON_EGG_CACHE'] = '/web/cache/trac/pybb.org'

import trac.web.main
app = trac.web.main.dispatch_request

Это просто создание WSGI приложения, обслуживающего trac-проект. Теперь его можно подцепить к superfcgi библиотеке. Библиотека superfcgi предоставляет команду superfcgi, которая в параметре —app принимает название модуля, где находится wsgi-приложение. Описываю я всё довольно сумбурно, но писать подробнее не могу — шибко лень :) Я просто это всё напишу здесь, потом кто-то будет искать через google, наткнётся, прочитает, что-то поймёт. Я сам иногда на свои старые посты натыкаюсь и иногда даже нахожу то, что успел забыть :D

В общем, spawn.sh файл для запуска trac такой:

Блог django на хабрахабре

Django Framework / Развертывание Django-проекта под nginx

Преамбула


Из нескольких способов развертывания Django я сразу отмёл mod_python, потому что мне не хотелось поднимать тяжеловесный Apache. Решил развернуть на легком веб-сервере. На данный момент основных легковесных альтернатив Апачу две — lighttpd и nginx. Первоначально я выбрал первый, но столкнулся с проблемами, связанными с URL. Я подумал, что, может, nginx будет работать получше, и развернул приложение на нём. В этом деле мне очень сильно помог один скринкаст, уже не помню точно чьего авторства.
Всё было отлично, но когда я захотел использовать админку Django(удобная вещь, кстати), меня постигло разочарование — форма логина показывалась, но при попытке войти меня выбрасывало на admin/. После получаса гугления, я нашёл топик на небезызвестном форуме Ивана Салагаева, в котором описывалось решение проблемы. После того, как я последовал описанным советам, все заработало на-ура. Представляю вашему вниманию необходимую конфигурацию сервера и Django.

Анатолий Ларин

Django + Nginx + FastCGI

Интро Уже пару месяцев я разбираюсь с Python & Django. И вот настало время выкладывать свои художества в сеть ) Правда, мой первый сайт на Django посвящен ведению отчетов по работе. Он довольно прост и хвалиться нечем. Вместо этого я расскажу как просто развертывается проект на Django + Nginx + FastCGI. Устанавливаем У меня на офисном сервере стоит [...]

Изучаем Django

Система развертывания (deploy system)

.clip { display: block; background: #EEE; border: 1px dashed #999; padding: 1em 1em 0 1em; }

Как я и обещал в предыдущей серии, посвящаю этот пост нашей системе развертывания.

Система самописная, достаточно тесно связана с процессом разработки и реализована при помощи sh-скрипта.

Общая схема

На рисунке приведена немного сумбурная схема процесса развертывания.

Разработка ведется с использованием SVN установленным на локальном сервере, там же расположен и локальный сервер MySQL. MySQL используется всеми при разработке, структура создается через initdb. Начальные данные в обязательном порядке (скоро узнаете почему) сохраняются либо в fixtures, либо в init.sql, а в случае прав пользователей создается команда manage.py.

После каждого коммита автоматически запускается скрипт развертывания на DEV версию проекта. При этом исходный код на сервере обновляется (или загружается если проекта не существует), а структура базы обновляется при помощи замечательного mysqldiff. На схеме этот процесс помечен цифрой 1.

DEV версия проекта — инструмент разработчиков, расположен на хостинге проекта, но закрыт для просмотра не из локальной сети. Обновляется после каждой загрузки кода в репозиторий.

Используется редко, в основном для проверки ошибок возникающих из-за разных версий ПО и ОС на компьютерах разработчиков и хостинге.

Когда проект готов для тестирования, менеджер проекта запускает (по ssh;) развертывание на TEST он же помечен цифрой 2 на схеме. Структура база данных переносится из DEV версии.

TEST версия проекта — инструмент тестировщиков, как и DEV расположен на хостинге проекта, но закрыт для просмотра не из локальной сети. Обновляется по запросу, когда система готова к тестированию.

Практически все тестирование проводится на этой версии, так как обновляется она только по запросу, разработчики спокойно продолжают работать над системой во время тестирования.

На этот раз файлы проекта не обновляются из репозитория, а копируются из DEV версии. Старая версия проекта удаляется. В сложной ситуации это дает больше свободы, и базу данных и файлы проекта мы можем подкорректировать на хостинге и эти изменения попадут в тестирование.

Процесс деплоя на TEST выполняется итеративно, пока не будут исправлены все обнаруженные ошибки. И тогда наступает час X, менеджер проекта достает большую красную кнопку и запускает развертывание на PROD версию.

PROD версия проекта — инструмент пользователей. Используется интернет пользователями по назначению. (например для связи бизнеса и СМИ).

Обновляется по запросу, после окончания тестирования.

Публичная версия обновляется исключительно с TEST версии, копированием файлов и структуры базы. Это с одной стороны дает гарантию что мы запустим именно тот код который был оттестирован, с другой подразумевает что любые изменения должны быть проверены (задеплоиться с DEV или репозитория нельзя).

Расскажу об одном интересном моменте, почему при деплое не теряются пользовательские данные. Дело в том, что mysqldiff генерирует ALTER срипт, который изменяет лишь структуру БД, но не трогает сами данные. Файлы загруженные пользователями хранятся в отдельном месте и подключаются в структуру проекта с помощью символической ссылки. Таким образом мы имеем три независимых версии со своими данными в базе и загруженными файлами.

Конфигурация системы

Система планировалась более-менее универсальной, поэтому у каждого проекта есть опции развертывания, которые должны храниться в файле deploy/params.sh. Основные параметры:

  • Параметры SVN репозитория, для скачивания и обновления исходного кода.
  • Параметры MySQL сервера, который используется для переноса изменений структуры на DEV.
  • Имя конечного конфигурационного файла, который формируется из шаблона для каждой версии проекта.
  • Путь к media и загружаемым файлам пользователя.
  • Базовые порты FCGI и SPHINX.
  • Команда выполняемая сразу после деплоя (обычно команда инициализации прав пользователей).
Параметры представлены как переменные и добавляются с помощью включения скрипта.

MySQL

С базой при деплое все достаточно просто, если её не существует, скрипт запускает создание базы manage.py initdb, Django загружает fixtures, скрипт запускает init.sql и в конце выполняет прописанную в конфиге команду. Огромное разнообразие методов начальной загрузки данных удовлетворяет любые даже самые сложные случаи.

Например, в свое время мы столкнулись со сложностью распределения прав пользователей по группам. На уровне fixtures или init.sql ну никак не получалось этого сделать, из-за того что на разных версиях проекта, созданные initdb права, имеют разные id. В итоге и появилась команда выполняемая в конце развертывания, которая используя стандартные методы Django, формирует необходимые группы пользоватей и распределяет права доступа.

Все эти сложности с начальными данными очень помогают в процессе разработки и при первом деплое на продакшн. Если что-то пошло не так, база сбрасывается и автоматически наполняется нужными данными. Очень удобно.

Если база данных уже создана, то при развертывании переносится только структура с помощью mysqldiff. Этот скрипт делает экспорт структуры двух баз данных (откуда и куда переносим), сравнивает эти данные и формирует sql скрипт для обновления целевой базы. Скрипт уже стандартными средствами СУБД применяется к базе. Причем при деплое на PROD, скрипт просматривается вручную, дабы в случае сбоя не удалить пользовательские данные.

Конфигурационные файлы

Одна из моих любимых функций нашей системы — генерация конфигурационных файлов.

Конфиг разработчиков хранится в отдельном файле base_settings.py а в стандартном settings.py всего одна строчка включения базовых настроек from base_settings.py import *.

Для настроек применяемых на хостинге создается специальный шаблон настроек template_settings.py в котором переопределяются нужные настройки из base_settings.py, причем следуя принципу DRY шаблонный файл всего один для всех трех версий системы.

Поведение специфичное для конкретной версии (имена баз данных, например, у всех разные) поддерживается макро-язык суть которого в замене конструкции {имя версии: значение} на значение. Допустим строка

DATABASE_NAME={dev:eshtab_dev}{test:eshtab_test}{prod:eshtab}
при развертывании на TEST будет исправлена на DATABASE_NAME = eshtab_test.

Но с другой стороны мы уже указали имя базы данных в params.sh, воскликнет внимательный читатель. Для решения этой проблемы активны специальные подстановки, вот примерный их список:

{instance}
DEV, TEST или PROD — версия системы.
{dbname}
имя базы данных.
{sitepath}
путь к файлам проекта.
{domain}
базовый адрес версии проектам (например dev.eshtab.ru).
{fcgi_port}
FCGI порт, используется как Django так и NGINX.
{sphinx_port}
порт поискового движка, используемого на наших проектах.
{media_path}
путь к статическим файлам.

Подстановки изумительны с точки зрения DRY, они используются как в Django так и в конфигурационных файлах SPHINX, NGINX, так и в скриптах запуска.

Макро-замены и подстановки осуществляются потоковым текстовым редактором sed. После замен settings.py заменяется шаблоном.

SPHINX, NGINX

Может быть это и не очень правильно, но конфигурационные файлы web-сервера, и поискового движка, также хранятся в репозитории и правятся программистами. С одной стороны возрастает ответственность, с другой стороны мы получаем больше контроля над системой.

Плюс, благодаря заменам и подстановке, на все версии системы по одному файлу конфигурации. Если их было бы по одному на каждую, правки доставляли некоторые неудобства. Вот небольшая часть конфигурационного файла веб-сервера:

{dev:#}{test:#}    server {
{dev:#}{test:#}        listen       80;
{dev:#}{test:#}        server_name .{domain};
{dev:#}{test:#}        rewrite ^/(.*) http://www.{domain}/$1 permanent;
{dev:#}{test:#}    
}

Как вы наверно догадались на DEV и TEST эти строки будут закомментированы, а на PROD веб-сервер будет переадресовывать запросы с domain на www.domain из эстетических соображений.

На правах заключения

Так работает наша замечательная система развертывания, если у вас остались какие-нибудь вопросы по ней, задавайте их в комментариях, с удовольствием отвечу. Особо мне будут интересны замечания и предложения.

Александр Соловьёв

Django performance: Apache vs Nginx

Неделю назад я сравнивал производительность и устойчивость работы nginx'а с Django с помощью mod_wsgi и fastcgi. Сравнение показало, что скорость работы при наличии быстрой локальной (читай - практически не оказывающей влияние) БД практически не отличается, отличается только количество используемых ресурсов.

А сегодня я наконец-то собрался посмотреть, что же будет, когда база данных находится на другом компе, а связь по wifi между веб-сервером и БД усугубляет проблему. :-) То есть весь смысл сегодняшних моих мучений - посмотреть на ситуацию с тормозящей базой данных (стало интересно после комментария Манлио). Заодно и хотелось посмотреть, как себя ведёт Apache.

Перед этим я таки запустил пару раз лёгкий тест (ab -n 100 -c 20) на Апач (с локальной базой данных), который показал, что апач не хочет использовать два моих ядра ни в какую. :-( Ни prefork, ни worker не использовали второе ядро и запрос в среднем занимал 28 мс, что в два раза дольше, чем nginx'овый показатель - 14 мс. Логически поразмышляв, можно понять, что тяжёлый Апач в любом случае работает медленнее nginx'а - второе ядро в два раза не ускорит (что и говорит показатель в 24 мс у nginx'а при работе с одним ядром :-).

Дальше PostgreSQL был запущен на другом ноуте. Апач я мерял как в prefork версии, так и в worker.

Первый вариант - ab -n 1000 -c 20:

  • apache - ~37 мс. Стабильно, в пределах 5 запусков разницы не было даже в миллисекунду.
  • nginx + mod_wsgi - ~50 мс. Ожидаемо.
  • nginx + fastcgi prefork - ~28 мс. В мозгу не укладывается, что оно настолько быстрее Апача! :-)

Второй вариант - при ab -n 3000 -c 500 - не слишком отличается. Апач и фастцги - такие же, мод_всги вырос до 55 мс.

В этот момент мне показалось, что mod_wsgi годится только когда нету БД (или задержками на её работу можно пренебречь). Однако, поразмыслив, я сделал ход конём - увеличил количество воркеров в нгинксе. :-) При 16 воркерах (проверено позже - 8 достаточно) и 500 одновременных запросов один отклик приходит в среднем раз в 28 мс. Теперь и результат фастцги укладывается, и апач выглядит толстым и тяжёлым, как обычно. ;-) Правда, каждый процесс nginx'а, работающий с джангой, кушает порядка 15 мегабайт. Хотя это в любом случае меньше, чем апач и fastcgi.

Выводы каждый может сделать сам для себя, но nginx + mod_wsgi однозначно - очень интересная комбинация.

Александр Соловьёв

Django performance: Apache vs Nginx

Неделю назад я сравнивал производительность и устойчивость работы nginx'а с Django с помощью mod_wsgi и fastcgi. Сравнение показало, что скорость работы при наличии быстрой локальной (читай - практически не оказывающей влияние) БД практически не отличается, отличается только количество используемых ресурсов.

А сегодня я наконец-то собрался посмотреть, что же будет, когда база данных находится на другом компе, а связь по wifi между веб-сервером и БД усугубляет проблему. :-) То есть весь смысл сегодняшних моих мучений - посмотреть на ситуацию с тормозящей базой данных (стало интересно после комментария Манлио). Заодно и хотелось посмотреть, как себя ведёт Apache.

Перед этим я таки запустил пару раз лёгкий тест (ab -n 100 -c 20) на Апач (с локальной базой данных), который показал, что апач не хочет использовать два моих ядра ни в какую. :-( Ни prefork, ни worker не использовали второе ядро и запрос в среднем занимал 28 мс, что в два раза дольше, чем nginx'овый показатель - 14 мс. Логически поразмышляв, можно понять, что тяжёлый Апач в любом случае работает медленнее nginx'а - второе ядро в два раза не ускорит (что и говорит показатель в 24 мс у nginx'а при работе с одним ядром :-).

Дальше PostgreSQL был запущен на другом ноуте. Апач я мерял как в prefork версии, так и в worker.

Первый вариант - ab -n 1000 -c 20:

  • apache - ~37 мс. Стабильно, в пределах 5 запусков разницы не было даже в миллисекунду.
  • nginx + mod_wsgi - ~50 мс. Ожидаемо.
  • nginx + fastcgi prefork - ~28 мс. В мозгу не укладывается, что оно настолько быстрее Апача! :-)

Второй вариант - при ab -n 3000 -c 500 - не слишком отличается. Апач и фастцги - такие же, мод_всги вырос до 55 мс.

В этот момент мне показалось, что mod_wsgi годится только когда нету БД (или задержками на её работу можно пренебречь). Однако, поразмыслив, я сделал ход конём - увеличил количество воркеров в нгинксе. :-) При 16 воркерах (проверено позже - 8 достаточно) и 500 одновременных запросов один отклик приходит в среднем раз в 28 мс. Теперь и результат фастцги укладывается, и апач выглядит толстым и тяжёлым, как обычно. ;-) Правда, каждый процесс nginx'а, работающий с джангой, кушает порядка 15 мегабайт. Хотя это в любом случае меньше, чем апач и fastcgi.

Выводы каждый может сделать сам для себя, но nginx + mod_wsgi однозначно - очень интересная комбинация.

Александр Соловьёв

Nginx + Django: mod_wsgi vs FastCGI

Вчера вечером таки связался с автором mod_wsgi (до этого были какие-то проблемы - он говорит, что мне отвечал, но у меня даже в спамбоксе пусто было) и скомпилировал nginx с mod_wsgi (ха-ха, как много решают слеши в нашей жизни ;-).

Запуск джанговского приложения под nginx'ом не вызвал абсолютно никаких проблем - использовался тот же файлик django.wsgi, который я приводил раньше для апача. Больше о настройке решил ничего не писать, потому как код ещё не стабильный и требует тестирования, потому использование где-то в реально жизни пока больному не показано.

Но тут начинается веселье - тестирование. ;-) Простая страничка, 15 запросов (PostgreSQL на этом же компе), инфы по этим запросам приходят мелочи (ещё хочу потестировать, чтоб было инфы побольше, а постгрес был на другом компе). 2 воркера (пробовал и 3, и 4 - выходит медленнее в любом варианте, на 2-4 мс). Два варианта запросов (ab -n 1000 -c 20 и ab -n 10000 -c 500) и три варианта серверов (mod_wsgi, prefork fastcgi, threaded fastcgi). Железо (всё равно интересно только в сравнении на одном железе и софте, потому конфигурация несущественна, но всё же) - Core 2 Duo T7300 и 2 Gb RAM.

При ab -n 1000 -c 20 (на каждый вариант сервера пришлось порядка 10-12 тестирований):

  • mod_wsgi стабильно выдаёт 14.2-14.3 мс на запрос
  • prefork fastcgi выдаёт 12.5-16.5 мс (в основном около 12, но иногда подскакивает), жрёт больше рамы - у меня xmobar1 показывает количество съеденной памяти, при mod_wsgi там на пару процентов (процент - 20 мегов) меньше всегда
  • threaded fastcgi выдаёт 24-25 мс на запрос - он использует только одно ядро, я пытался настроить в нгинксе upstream - он работает, но использует почему-то только 1 процесс

Т.е. в большинстве случаев при такой нагруженности фастцги выходит немного быстрее (хотя и кушает немножко больше ресурсов). Но... идём дальше? ;)

При ab -n 10000 -c 500 (тут вышло по 3-4 запуска):

  • mod_wsgi выдаёт 13-14 мс. Каждый воркер хавает примерно 21/15 мегов памяти (VSZ/RSS)
  • prefork fastcgi выдаёт 15.5-17 мс на запрос, но при этом запускается от 40 до 50 обслуживающих процессов, каждый из которых кушает 16-20 VSZ (10-13 RSS) мегов памяти! По xmobar'у расход выходит до 50% (скачками, обычно около 45-48) относительно 33% у wsgi. Это лишних 300 мегов оперативки!
  • threaded fastcgi - самый интересный вариант. При таком количестве одновременных запросов он умирает. При -c 100 - тоже умирает. При -c 50 - живёт, но скорость выходит чуть ниже, чем при -c 20, а рабочий процесс хавает до 300 мегов VSZ.

Что тут можно сказать? Ждём, когда mod_wsgi станет стабильным! :-)


  1. xmobar - это такой статусбар на хаскеле, показывает состояние системы и вообще чего мне захочется  

Александр Соловьёв

Nginx + Django: mod_wsgi vs FastCGI

Вчера вечером таки связался с автором mod_wsgi (до этого были какие-то проблемы - он говорит, что мне отвечал, но у меня даже в спамбоксе пусто было) и скомпилировал nginx с mod_wsgi (ха-ха, как много решают слеши в нашей жизни ;-).

Запуск джанговского приложения под nginx'ом не вызвал абсолютно никаких проблем - использовался тот же файлик django.wsgi, который я приводил раньше для апача. Больше о настройке решил ничего не писать, потому как код ещё не стабильный и требует тестирования, потому использование где-то в реально жизни пока больному не показано.

Но тут начинается веселье - тестирование. ;-) Простая страничка, 15 запросов (PostgreSQL на этом же компе), инфы по этим запросам приходят мелочи (ещё хочу потестировать, чтоб было инфы побольше, а постгрес был на другом компе). 2 воркера (пробовал и 3, и 4 - выходит медленнее в любом варианте, на 2-4 мс). Два варианта запросов (ab -n 1000 -c 20 и ab -n 10000 -c 500) и три варианта серверов (mod_wsgi, prefork fastcgi, threaded fastcgi). Железо (всё равно интересно только в сравнении на одном железе и софте, потому конфигурация несущественна, но всё же) - Core 2 Duo T7300 и 2 Gb RAM.

При ab -n 1000 -c 20 (на каждый вариант сервера пришлось порядка 10-12 тестирований):

  • mod_wsgi стабильно выдаёт 14.2-14.3 мс на запрос
  • prefork fastcgi выдаёт 12.5-16.5 мс (в основном около 12, но иногда подскакивает), жрёт больше рамы - у меня xmobar1 показывает количество съеденной памяти, при mod_wsgi там на пару процентов (процент - 20 мегов) меньше всегда
  • threaded fastcgi выдаёт 24-25 мс на запрос - он использует только одно ядро, я пытался настроить в нгинксе upstream - он работает, но использует почему-то только 1 процесс

Т.е. в большинстве случаев при такой нагруженности фастцги выходит немного быстрее (хотя и кушает немножко больше ресурсов). Но... идём дальше? ;)

При ab -n 10000 -c 500 (тут вышло по 3-4 запуска):

  • mod_wsgi выдаёт 13-14 мс. Каждый воркер хавает примерно 21/15 мегов памяти (VSZ/RSS)
  • prefork fastcgi выдаёт 15.5-17 мс на запрос, но при этом запускается от 40 до 50 обслуживающих процессов, каждый из которых кушает 16-20 VSZ (10-13 RSS) мегов памяти! По xmobar'у расход выходит до 50% (скачками, обычно около 45-48) относительно 33% у wsgi. Это лишних 300 мегов оперативки!
  • threaded fastcgi - самый интересный вариант. При таком количестве одновременных запросов он умирает. При -c 100 - тоже умирает. При -c 50 - живёт, но скорость выходит чуть ниже, чем при -c 20, а рабочий процесс хавает до 300 мегов VSZ.

Что тут можно сказать? Ждём, когда mod_wsgi станет стабильным! :-)


  1. xmobar - это такой статусбар на хаскеле, показывает состояние системы и вообще чего мне захочется  

Александр Соловьёв

Nginx и WSGI

Сегодня наткнулся на просто невероятную вещь - mod_wsgi для nginx'а. На английском упоминаний нету вообще нигде, но не сомневаюсь, что они скоро появятся. :)

UPD. Он, конечно, совсем новый и ещё не юзабельный для продакшена, но, судя по всему, пока разработчик порядочно активен - только что добавился TODO

Александр Соловьёв

Nginx и WSGI

Сегодня наткнулся на просто невероятную вещь - mod_wsgi для nginx'а. На английском упоминаний нету вообще нигде, но не сомневаюсь, что они скоро появятся. :)

UPD. Он, конечно, совсем новый и ещё не юзабельный для продакшена, но, судя по всему, пока разработчик порядочно активен - только что добавился TODO

Метки

.net .NET C# 1.2 2009 2010 404 error admin ajax amazon and apache api archlinux asp.net async asynchronous autocomplete bash blender blog blogengine blogs book bootstrap bot bpython buildout byteflow bzr C C++ cache cbv Chaco checkio chrome ci ckeditor class based views clojure closure cms cms с удобной админкой code coding style COM comet competition conference ConfigParser contest Context continuous integration CouchDB coverage CppCMS cpyext cpython csrf CSS curl custom model fields cython database db dbm dbqueries debian debug debugging decorator decorators deploy deployment descriptor design dev devconf developers development diveintopython Django django 1.2 django 1.3 django advent django framework django template django trunk django weblog django-admin-tools django-cms django-compressor django-hosts django-piston django-registration django-sphinx django.admin djangoadvent djangocms djangodash doc documentation drupal e-legion eclipse EGit emacs encoding Enthought epoll erlang event exception ExtJS fabric facebook fastcgi finaloption fixtures fonts forms formset fp framework freebsd freeswitch fs2web ftp fun funcparserlib functional gae gamin gandi generic views gettext gevent gil git github gitosis Google Google App Engine Google Translate google wave Google Web Toolkit grab greenlet gtd gui haskell hg hgshelve highlighter hosting how-to howto html html5lib Hudson humor i18n icfpc ide idiomatic image-scripting improvements Internet ipython ironpython izmenimsya.ru jabber java javascript jenkins jetbrains JIT job jquery json jstree jython kde kiev kiyv kyivpy l10n ldap library libs Life Links linux Linux & Unix LLVM logging lxml Mac OS X magic mail markdown Matplotlib Mayavi maybe mediavirus meetup memcache memory messages metaclass middleware migration mkd model models mod_wsgi mongodb monitoring mptt musicmans.ru musicx my-projects mysql netCDF networkx newforms newforms-admin news nginx Nhibernate nix nose NoSQL numpy oop open source OpenID openoffice opster optimization oracle orm os pagination parsing path pdf PDF-принтер PEP PEP8 performance perl personality php picture-driven computing PIL pinax pingback pip plasma plone plugin plugins postgresql programming psycopg2 py2exe pybb pybbm pycamp pycharm pycon pycow pycurl pydev pygtk pylons PyNGL pypy PyQt4 pyrad pyramid PySide Python Python 2.5 python 2.7 python 3 python-mssql python3 pywinauto Qt Qt4 queue rabbitmq radius raw sql re redis redsolution redsolution cms regexp regular expressions release repoze.bfg RequestContext reusable apps robokassa rss ru ruby ruby-on-rails sample satchmo scalability SciPy scraping screencast search selenium self.error seo server setattr settings setuptools shell sikuli sms snippet socket.io software sorting south sphinx sql sqlalchemy sqlite ssh startup subversion svn SyntaxHighlighter system tags tdd tddspry teh drama template templates templatetags test testing thinkpad threading threads tips tips and tricks tools tornadio tornado tornado server tricks tutorial tweepy twisted twitter typography uapycon Ubuntu ucsvlog uml Uncategorized unicode unit test UnitTest Unladen Swallow upload urllib urls utf-8 uwsgi validation vcs versioning video vim virtualenv Visual Studio voip wave web web-devel web-services web-разработка webdev webkit webpy webtest widget widgets Win API windows Wirbel work wrapper wsgi wxPython wxWidgets wysiwyg xapian xml xmonad xmpp xpath yandex youtube zip zomg zope автоматизация администрирование администрирование django админка алгоритмы архитектура базы данных Без рубрики безопасность библиотеки блоге бот видео Визуализация данных вконтакте Все записи гвидо ван россум граббер графика графы декоратор дескриптор дескрипторы документация заметки идея интересное киев Клиентам книги конференция личное математика метаклассы модели модули морфология мысли невозможное новости о облачные вычисления обо мне Обработка данных оптимизация Основная лента парсинг перевод Питон поебень поиск правила кодирования программирование Проектирование производительность работа рабочее размышлизмы Разное разработка приложений разработки регулярные выражения сайт событие события ссылки статьи тестирование тесты Тюмень фигня философия формы форум Хабрахабр хакинг шаблоны шаблоны проектирования эксперимент Эксперименты юмор Яндекс