Лаборатория → Сравнение производительности Django-проектов, размещенных на виртуальном хостинге с FastCGI и WSGI
Для создания работоспособного виртуального хостинга, который мог бы предоставлять клиентам возможность размещать Django-проекты, мы изучили три основных способа их размещения: с использованием mod_python web-сервера Apache2, FastCGI и mod_wsgi.
Родной модуль mod_python был отвергнут сразу, поскольку он не позволяет запускать сценарии от имени выбранного пользователя. Остальные два метода изначально казались равнопривлекательными, хотя про mod_wsgi на профессиональных форумах отзываются заметно лучше.
Установка и настройка:
Чем привлекает FastCGI? Он прост в настройке, принципы работы с ним хорошо известны и его внедрение не представляет никаких сложностей. Для нормальной работы django-приложения достаточно правильным образом сконфигурировать VirtualHost web-сервера Apache2 и написать простой сценарий запуска для FastCGI:
#user defined
ServerAdmin admin@django-test.locum.ru
ServerName django-test.locum.ru
#end
DocumentRoot "/home/versus/projects/django-test.locum.ru"
SuexecUserGroup versus customers
AddType fastcgi-script .fcgi
Alias /media/ /home/versus/projects/django-test.locum.ru/media/
ScriptAlias / /home/versus/projects/django-test.locum.ru/django.fcgi/
CustomLog "/var/log/apache2/django-test.locum.ru.custom.log" combined
ErrorLog "/var/log/apache2/django-test.locum.ru.error.log"
При этом статические файлы (изображения, звуки и прочие) раздаются непосредственно web-сервером, что значительно повышает скорость работы приложения в целом.
#!/usr/bin/python
import os
import sys
from flup.server.fcgi import WSGIServer
from django.core.handlers.wsgi import WSGIHandler
sys.path.insert(0, '/home/versus/projects/django-test.locum.ru/app/')
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
WSGIServer(WSGIHandler()).run()
Основным преимуществом FastCGI является, пожалуй, возможность устанавливать переменные Django прямо в файле конфигурации Apache. Теоретически это дает возможность иметь один на всех сценарий запуска проекта. Кроме того, изменения в любом файле проекта сразу же становятся видны: какое-либо кеширование отсутствует.
Процедура запуска WSGI во многом идентична FastCGI: в систему необходимо установить соответствующий пакет с mod_wsgi и так же, как и в предыдущем случае, создать необходимые конфигурационные файлы.
#user defined
ServerAdmin admin@django-test.locum.ru
ServerName django-test2.locum.ru
#end
DocumentRoot "/home/versus/projects/django-test2.locum.ru"
Alias /media/ /home/versus/projects/django-test2.locum.ru/media/
WSGIDaemonProcess django-test2 user=versus group=customers threads=2
WSGIProcessGroup django-test2
WSGIScriptAlias / /home/versus/projects/django-test2.locum.ru/django.wsgi
CustomLog "/var/log/apache2/django-test.locum.ru.custom.log" combined
ErrorLog "/var/log/apache2/django-test.locum.ru.error.log"
Каталог, содержащий статические документы, обрабатывается непосредственно web-сервером.
#!/usr/bin/python
import os
import sys
sys.path.insert(0, '/home/versus/projects/django-test2.locum.ru/app/')
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
В этой ситуации все необходимые переменные необходимо устанавливать уже в файле сценария запуска, поэтому придется создавать отдельные файлы для каждого django-проекта. С одной стороны, это не очень хорошо — появляется дублирование и возможны проблемы с неправильной конфигурацией. С другой стороны, такой подход дает большую гибкость.
WSGI кеширует модули python, поэтому изменения в проекте вступают в силу не сразу, а только либо после перезагрузки web-сервера (что недопустимо в коммерческой эксплуатации), либо при изменении timestamp конфигурационного файла.
Тестируем производительность
Так какой же способ быстрее? Для ответа на этот вопрос мы взяли стандартное django-приложение, которое отображает всего одну страничку текста и картинку.
Методика тестирования была крайне проста: требовалось определить, какой способ затратит меньше времени на многократное повторение запросов. Для этого был написан специальный сценарий, который 1000 раз загружал главную страницу проекта.
#!/bin/bash
for i in `seq 1 1000`; do
wget -O /dev/null "http://django-test2.locum.ru/" > /dev/null 2> /dev/null
done
В процессе выполнения при помощи системной утилиты time замерялось время, необходимое для загрузки всех 1000 запросов. Сценарий выполнялся на локальной машине, чтобы избежать возможных накладок сети. И вот какие результаты мы получили:
WSGI | FastCGI | |
Количество запросов | 1000 | 1000 |
Время исполнения | 00:06.648 | 02:55.243 |
Системное время | 00:01.484 | 00:01.672 |
Разница получилась больше, чем в 20 раз! После этого эксперимента мы однозначно выбрали mod_wsgi в качестве сервера для django-проектов. Конечно, пришлось учесть особенности такого подхода: в любой момент прямо с панели управления хостингом можно отдать команду на перезапуск сервера (touch для сценария запуска) и восстановить содержимое индивидуального сценария по умолчанию на тот случай, если пользователь случайно что-то неправильно написал.
<VirtualHost 127.0.0.1>
#user defined
ServerAdmin admin@django-test.locum.ru
ServerName django-test.locum.ru
#end
DocumentRoot «/home/versus/projects/django-test.locum.ru»
SuexecUserGroup versus customers
AddType fastcgi-script .fcgi
Alias /media/ /home/versus/projects/django-test.locum.ru/media/
ScriptAlias / /home/versus/projects/django-test.locum.ru/django.fcgi/
CustomLog «/var/log/apache2/django-test.locum.ru.custom.log» combined
ErrorLog «/var/log/apache2/django-test.locum.ru.error.log»
</VirtualHost>
При этом статические файлы (изображения, звуки и прочие) раздаются непосредственно web-сервером, что значительно повышает скорость работы приложения в целом.
#!/usr/bin/python
import os
import sys
from flup.server.fcgi import WSGIServer
from django.core.handlers.wsgi import WSGIHandler
sys.path.insert(0, ‘/home/versus/projects/django-test.locum.ru/app/’)
os.environ[‘DJANGO_SETTINGS_MODULE’] = ‘settings’
WSGIServer(WSGIHandler()).run()
Основным преимуществом FastCGI является, пожалуй, возможность устанавливать переменные Django прямо в файле конфигурации Apache, что, теоретически, дает возможность иметь один на всех сценарий запуска проекта. Кроме того, изменения в любом файле проекта сразу же становятся видны: какое-либо кеширование отсутствует.
Процедура запуска WSGI во многом идентична FastCGI: в систему необходимо установить соответствующий пакет с mod_wsgi и также, как и в предыдущем случае создать необходимые конфигурационные файлы.
<VirtualHost 127.0.0.1>
#user defined
ServerAdmin admin@django-test.locum.ru
ServerName django-test2.locum.ru
#end
DocumentRoot «/home/versus/projects/django-test2.locum.ru»
Alias /media/ /home/versus/projects/django-test2.locum.ru/media/
WSGIDaemonProcess django-test2 user=versus group=customers threads=2
WSGIProcessGroup django-test2
WSGIScriptAlias / /home/versus/projects/django-test2.locum.ru/django.wsgi
CustomLog «/var/log/apache2/django-test.locum.ru.custom.log» combined
ErrorLog «/var/log/apache2/django-test.locum.ru.error.log»
</VirtualHost>
Так же, как и в предыдущем случае, каталог, содержащий статические документы, обрабатывается непосредственно web-сервером.
#!/usr/bin/python
import os
import sys
sys.path.insert(0, ‘/home/versus/projects/django-test2.locum.ru/app/’)
os.environ[‘DJANGO_SETTINGS_MODULE’] = ‘settings’
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
В этом случае все необходимые переменные необходимо устанавливать уже в файле сценария запуска, поэтому придется создавать отдельные файлы для каждого django-проекта. С одной стороны это не очень хорошо — появляется дублирование и возможны проблемы с неправильной конфигурацией. С другой стороны, такой подход дает большую гибкость.
WSGI кеширует модули python, поэтому изменения в проекте вступают в силу не сразу, а только либо после перезагрузке web-сервера (что недопустимо в коммерческой эксплуатации), либо при изменении timestamp конфигурационного файла.
Тестируем производительность
Так какой же способ быстрее? Для ответа на этот вопрос мы взяли стандартное django-приложение, которое отображает всего одну страничку текста и картинку.
Тест не о чем.
Начнем с того, что абсолютно не корректное название статьи. Два протокола сравниваются в абсолютно специфичном окружении, в котом тестируются не они, а их конкретные реализации. Но это можно списать на желание сделать «замануху».
Потом, почему для проверки fastcgi режима не используется штатный враппер вокруг флапа ./manage.py funcfcgi? Если списывать на специфичную область применения, то это никак не отражено и не прокомментировано.
Далее, в предложенном варианте, fastcgi работает в cgi режиме, что в принципе противоречит заданному тестовому раскладу и вводит читателей (и писателя) в заблуждение.
Ну и, абсолютно не отражено почему настройки именно такие, например почему для демон-процесса mod_wsgi указана количество тредов 2, а не 10 допустим. Это, конечно, при секвентальных запросах роли не играет, но всё же.
И зачем было придумывать свой велосипед со «стрелялкой» в виде wget, a не были использованы традиционные, проверенные и более точные инструменты.
В общем, статью явно писал человек не понимающий что он хочет сделать и зачем. Из-за это тестирование абсолютно не отражает реальной ситуации и приводит к абсолютно необоснованным выводам.
Так же складывает негативное впечатление о профессионализме всей компании.
Желаю удачи, и внимательной работы над ошибками.
Александр, большое спасибо за профессиональный комментарий!
Вы правы, тестируются два протокола в абсолютно конкретном, одинаковом и специфичном окружении — в том, которое установлено на конкретных серверах. Желание устроить «замануху», поверьте, было далеко не главным. Все-таки наша первоочередная задача — обеспечивать надежность и производительность технологий, которые мы предоставляем.
При тестировании мы использовали рекомендуемые разработчиками фреймворка конфигурации FastCGI и WSGI. Вполне возможно, что при других настройках и в другом окружении есть смысл использовать что-то другое. Но, на наш взгляд, если речь идет о предоставлении услуг, то логично выбирать проверенные и стабильные варианты настройки, которые рекомендуют создатели фреймворка.
Что касается режима работы FastCGI, то тут играет решающую роль настройка самих серверов. У нас сценарии FastCGI по ряду причин запускаются как CGI, а не через сокет, поэтому пока выбирать не приходится.
Мы не ставили перед собой задачу всестороннего тестирования производительности django на всех программно-аппаратных конфигурациях. Есть конкретный сервер, конкретные настройки и тест, который покажет отличие одного подхода от другого. Если вы считаете, что у работы через WSGI есть недостатки перед FastCGI и последний может работать быстрее, предлагайте свои решения, мы будем признательны.
На каких тарифных планах возможно использование django?
Django-приложения запускаются на всех наших тарифных планах, более подробно ознакомиться с тарифными планами вы можете кликнув по ссылке