About Blog Dev | Alfa Romeo SZ Conkeror wishlist

All articles, tagged with “apache”

Django performance: Apache vs Nginx - en

Just a week ago I have compared performance and stability of nginx working with Django through mod_wsgi and fastcgi. Comparison revealed that performance with fast local DB (i.e. time of DB work is negligibly small) is almost identical and all the difference is in used resources.

Today at last I have time to look, what will be, when database is located at other computer and WiFi connection between application and DB worsening situation. :-) I.e. sense of my today’s actions is looking at situation, when DB is slow (this is interesting for me after Manlio’s commentary in previous post). Additionally I wanted to look at Apache’s behavior.

Before doing that I runned lightweight test (ab -n 100 -c 20) on Apache (with local database), which showed up that Apache don’t want to use my two cores. :-( Nor prefork, neither worker don’t used second core and time between requests was around 28 ms, which is two times to nginx’ 14 ms. Logic thoughts said that heavy-weight Apache in any case is slower than nginx — second core will not improve performance in two times (so says nginx’ 24 ms when working with one core :-).

Further PostgreSQL was launched at another laptop. Apache was tested in both versions, prefork and worker and displayed no difference, so I’ve stopped on worker.

First — ab -n 1000 -c 20:

  • Apache — ~37 ms. Very stable, difference in time between 5 runs was lesser than 1 ms.
  • nginx + mod_wsgi — ~50 ms. Expected (as Manlio said, nginx is blocked while working with application, which is blocked by request to DB).
  • nginx + fastcgi prefork — ~28 ms. I can’t believe it is so faster than Apache! :-)

Second test — ab -n 3000 -c 500 — is not very distinguished from first. Apache and fastcgi — same result, mod_wsgi raised to 55 ms.

At that moment I thought that mod_wsgi is only suited for application without database (or when delays for its work is negligibly small). But, thought over, I made knight’s move — raised number of workers in nginx. :-) With 16 workers (tested after — 8 is enough) and 500 concurrent connections delay between answers is 28 ms. Now I can believe in fastcgi result and Apache is heavy and fat, as usual. ;-) Thought, every nginx’ process, which works with Django, eats around 15 mb of RAM. However apache and fastcgi (threaded, forked) want bigger amount of memory.

Everyone can do summary for himself, the only one thing I can say unambiguously — nginx + mod_wsgi is very interesting combination.

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 однозначно - очень интересная комбинация.

Apache + mod_wsgi + Django

Меня тут попросили описать то, как я запускаю джанговские приложения в апаче. Я решил не растягивать резину в долгий ящик и просто привести свой конфиг с комментариями. :)

<VirtualHost *>
    ServerAdmin piranha@piranha.org.ua
    ServerName piranha.org.ua
    ServerAlias www.piranha.org.ua

    # директива говорит о том, что это конкретное приложение будет исполняться
    # в процессе-демоне с названием piranha
    WSGIProcessGroup piranha
    # Собственно описание этого демона. 2 процесса, максимум 1000 запросов.
    # Сайт не нагруженный, больше и не надо. :)
    WSGIDaemonProcess piranha user=piranha group=www-data threads=2 maximum-requests=1000
    # Главная, практически, директива. Файлик с описанием приложения. См. ниже.
    WSGIScriptAlias / /home/piranha/web/byteflow/byteflow/django.wsgi

    # Решил оставить, чтоб не забывали про него. :)
    # Кеширование картинок и прочих статических файлов.
    <IfModule mod_expires.c>
        <FilesMatch "\.(jpg|gif|png|css|js)$">
            ExpiresActive on
            ExpiresDefault "access plus 3 days"
        </FilesMatch>
    </IfModule>

    # Описание расположения статических файлов.
    Alias "/admin-media/" "/usr/local/lib/python2.4/site-packages/django/contrib/admin/media/"
    <Location "/admin-media/">
        SetHandler None
    </Location>

    Alias "/media/" "/home/piranha/web/byteflow/media/"
    <Location "/media/">
        SetHandler None
    </Location>

    # Логи. ;)
    LogLevel warn
    CustomLog /home/piranha/web/logs/piranha.access.log combined
    ErrorLog /home/piranha/web/logs/piranha.error.log
</VirtualHost>

А вот тот самый файлик, в котором описывается, как запускать приложение:

import sys
import os
import os.path

sys.path.insert(0, os.path.dirname(__file__))
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

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

Кратко и незамысловато. Годится для любого проекта в силу независимости от места расположения. :)

Вот и всё. Файлик django.wsgi лежит в директории проекта, джанга лежит в пути Python‘а (у меня вот в /usr/local/, потому как последний trunk и пакета для него, естественно, нету), всё работает прекрасно.

P.S.И, естественно, апач надо релоадить (apache2ctl graceful) после изменений в конфиге или в питон-коде приложения.