WSGI серверы кратко
За последние несколько дней обнаружилась (для меня) уйма интересных WSGI серверов. Я уже довольно давно использую (естественно, для Джанги) Apache mod_wsgi для продакшена и CherryPy’евский WSGI-сервер для разработки. Но недавно обнаруженный fapws2 заинтересовал меня и я наконец-то собрался его скомпилировать (основная загвоздка была в необходимости обновления libevent), потом моё внимание обратили на cogen, и вот сегодня уже — на spawning.
И я решил взять и погонять всех сразу apachebenchmark’ом. Тестировал просто — “ab -c 50 -n 500”, ничего особенно не тюнинговал, тестирование на абсолютную объективность и точность не претендует. Всех конкурентов запускал так, чтоб они могли скушать оба ядра процессора (иначе это было бы не спортивно со стороны Spawning’а, который запускает несколько процессов и может использовать все ядра).
Итак, протестированные герои:
- Apache2 mod_wsgi 2.0 daemon mode
- Twisted
- CherryPy
- Spawning
- Cogen
- Fapws2
Каждый из них работает как веб-сервер для джанги с byteflow (в качестве БД использован дамп этого самого блога). Каждый запущен в двух экземплярах, сидит за nginx’ом, исключая Spawning, у которого запущено два процесса и сидит он сам.
Вот результаты.
Лидеры — fapws2 и совсем немножечко медленее — cogen. На погрешность я бы не списывал, потому что два дня назад такая же ситуация была, и при каких условиях ни тестирую — fapws2 самую чуточку быстрее. Что характерно для лидеров — у них даже самые долгие запросы в 2 секунды укладываются, не то, что у других.
Аутсайдеры — CherryPy со своими 5,5 секундами на самом длинном запросе и Spawning, который так хвалили, со своими 4 секундами на длинный запрос и 80 Мб скушанного ОЗУ — это против 32 у фапвса и 40 у когена!
Про Твистед и Апач можно сказать, что Твистед в принципе немного быстрее, но смысла никакого использовать всё равно нету. Если хочется скорости — есть fapws2 или cogen, если хочется огромного количества фич — есть Апач, который почти всегда есть… В общем, не вижу смысла.
Между cogen и fapws2 тоже можно выбрать: cogen написан на чистом питоне (он использует py-epoll), а fapws2, использующий libevent, имеет внутри кусок C, и потому его необходимо компилировать (к примеру, для винды это — чистейшее мучение, на винде я бы использовал коген). Но fapws2 явно несколько меньше ОЗУ хочет, что приятно в стеснённых условиях VPS, ну и немножечко, но быстрее. ;-)
Так что буду я, похоже, на fapws2 переползать. Тем более у моего VPS целых 4 ядра, зря пропадают с апачем только… :-)
Comments
Сашко, а под виндой cogen ты и не запустишь, так как epoll — чисто линуксовый механизм;) и под freebsd тож, там kqueue
/me пока-что остановился на cogen, траблов не наблюдаю, да и код иногда интересно покурить =) а c С тяжко как-то
А, я что-то увлёкся. :) Но cogen для винды юзает iocp просто, вот и всё. А во фре — таки kqueue.
А под nginxовским mod_wsgi не пробывал?
Нет, руки не дошли. К сожалению, его для джанги в продакшене особо не поиспользуешь — он же блокирует при случае весь процесс nginx’а, а это не очень весело.
Вот тут не понял:
Почему пропадают-то? Раз он плодит отдельные процессы, то ОС нормально раскидает их на все доступные ядра.
Не раскидает, потому что я юзаю фичу mod_wsgi — daemon mode. При этом вся джанга выделяется в один отдельный процесс (ты если в результаты посмотришь, можешь их увидеть запущенные под моим пользователем, а не под апачевским), и, соответственно, юзает только одно ядро. Зато апачевские детки маленькие получаются, без питона инсайд. :)
ну привет
WSGIDaemonProcess ipidevtrac user=ipidevtrac group=nogroup processes=4 threads=16
?
на самом деле при daemon режиме mod_wsgi форкается как раз вместе с питоном внутри. Зато не грузится и парсистся каждый раз, а просто отправляет wsgi на обработку существующему форку. При этом может ещё и потоки создавать (питоновские, т.е. аккурат в питоновском потоке вызывает application(env, get_response)) чтобы долгие запросы не блочили весь форк.
only worker_mpm конечно.
Чорт, а слона-то я и не заметил. Я как-то абсолютно пропустил
processes. :\В общем, попробовал с
processes=4 threads=16, выходит 25 запросов в секунду (24.8-24.97). Но при этом возникает 4 процесса, каждый по 30 мегов. :processes=2 threads=4даёт результаты получше (25.5), и эти два процесса едят мегов по 22-23, что уже явно лучше.В общем, апач — не аутсайдер, но пока cogen и fapws2 — быстрее. А насколько апач быстр по сравнению с ними у тебя? Не хочешь запустить ab у себя?
Не кажется мне, что он вот так возьмёт и ни с чего обгонит.
конечно просто так он не обгонит — с чего бы это :). Апач надо очень грамотно собирать, не включая огромную кучу ненужных модулей. Часто я делаю лишь autoindex alias dir logio log_config rewrite so mime authz_host info env setenvif negotiation — мне этого за глаза хватает (в дефолтной поставке модулей раза в три поболе). Только статическая линковка. Ещё к этому всему надо грамтно настроить worker mpm — по дефолту там очень щадящие настройки.
Если настроение будет — прогоню тест, похожий на твой.
Я в курсе про собирание без лишних модулей, но возиться мне лень. :) Проще разобраться с runit’ом и использовать fapws2.
Ну в общем если сделаешь, то это будет хорошо. :)
Интересно, что в cogen написано: “HTTP handling code taken from the CherryPy WSGI server”. Выигрыш, таким образом, получается именно в несколько другой организации обработки запросов.
Да, прикольная тема. Я ещё хочу yield потестировать, но пока с ним траблы есть, вот с автором переписываюсь…
Запости пожалуйста результаты.
Что то я не пойму зачем ставить nginx перед апачем? apache + worker_mpm + mod_wsgi2 рвёт на моей машинке любые варианты с не-на-си написанными серверами.
У меня вот прямо сейчас fapws2 в среднем 1800 мс на запрос, апач — 1980. У питоновского когена — 1810, при этом оно не может загрузить проц на 100% — колеблется 97-98 постоянно.
1.8сек на запрос?! При столь тяжелой бизнес-логике производительность сервера толком ничего не меняет (:
Ога, я сча решил плюнуть и протестировать их на тупом приложении, которое делает
return HttpResponse("hello world"). Но пока нету настроения написать и опубликовать что-то, а вкратце — fapws2 всех, кроме когена, в два раза обгоняет. Коген где-то на 20% медленнее.Александр, а как получилось собрать libevent? Я на убунте пробовал собрать — что-то не вышло.
Я соврал. Fapws2 и mod_wsgi рулят, cogen отстаёт в 2 раза, остальные ещё медленнее.
я много копался в исходнике mod_wsgi.c. Там просто нечему тормозить (:
Причём, все же, и fapws2 с его libevent он, скорее всего, может обогнать при правильной настройке. Я уже запланировал сей бенчмарк на выходные ))
Давай-давай, у меня на этом приложении вышло 3900 запросов для fapws2 и 3500 для mod_wsgi при такой настройке:
:D С демон-модом вышло 3100.
Как поставить fapws2 под убунтой? Нашел libevent в исходниках, скомпилировал, но не заработало.
Есть какой-то более быстрый путь?
Ну, у меня libevent 1.4.6 скомпилировался очень просто. ./configure && make && make install. А что значит “не заработало”?
1.4.3 пока лучше — в 1.4.4..1.4.6 народ ещё не уверен.
вот ошибка.. Поставил libevent, fapws2 не ставится.
root@z:/usr/local/dl/fapws2-0.3# python setup.py install We will use the followinf libevent sources: ./libevent
running install running build running build_py running build_ext building ‘_evhttp’ extension gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I./libevent -I/usr/include/python2.5 -c fapws2/_evhttp.c -o build/temp.linux-x86_64-2.5/fapws2/_evhttp.o fapws2/_evhttp.c:24:27: error: http-internal.h: No such file or directory fapws2/_evhttp.c:25:17: error: log.h: No such file or directory fapws2/_evhttp.c: In function ‘send_error’: fapws2/_evhttp.c:35: warning: implicit declaration of function ‘evhttp_response_code’ fapws2/_evhttp.c:38: warning: implicit declaration of function ‘evhttp_send_page’ fapws2/_evhttp.c: In function ‘evhttp_handle_request’:
Ну собственно оно хочет, чтоб сорцы либевента лежали в
./libevent. Так что либо переложи, либо измени путь. :)Спасибо, все получилось. По дороге пришлось в setup.py исправить путь к libevent.so с /usr/lib/libevent.so на /usr/local/lib/libevent.so
Попробовал запустить byteflow через fapws2, взял конфиг из примеров fapws2 для джанги. Ругаецца, говорит,
We have an error in the python code associated to the url :/ Traceback (most recent call last): File “run.py”, line 25, in generic res=django_handler.handler(environ, start_response) File “/usr/lib/python2.5/site-packages/fapws2/contrib/django_handler.py”, line 7, in handler for key,val in res.headers.items(): AttributeError: ‘HttpResponseRedirect’ object has no attribute ‘headers’
Есть предложение добавить готовый конфиг для fapws2 в byteflow..
Аа, я забыл автору патч отправить. Замени res.header.items на res.items пока, а я тут с автором всё дообсуждаю.
Как можно вместе запустить fapws2 и nginx или fapws2 и lighthttpd? Только через fastcgi или еще можно как-то?
Byteflow не запускается под fapws2. Выдает ошибку:
We have an error in the python code associated to the url :/ Traceback (most recent call last): File “run.py”, line 21, in generic res=django_handler.handler(environ, start_response) File “/usr/lib/python2.5/site-packages/fapws2/contrib/django_handler.py”, line 5, in handler res=djhand(environ, start_response) File “/usr/lib/python2.5/site-packages/django/core/handlers/wsgi.py”, line 216, in call response = self.get_response(request) File “/usr/lib/python2.5/site-packages/django/core/handlers/base.py”, line 67, in get_response response = middleware_method(request) File “/home/z/byteflow/apps/middleware/url.py”, line 76, in process_request if not self._urlExists(old_url[1]): File “/home/z/byteflow/apps/middleware/url.py”, line 108, in urlExists if resolve(path) is None: raise Http404 # None?!? You mean 404… File “/usr/lib/python2.5/site-packages/django/core/urlresolvers.py”, line 299, in resolve return getresolver(urlconf).resolve(path) File “/usr/lib/python2.5/site-packages/django/core/urlresolvers.py”, line 238, in resolve for pattern in self.urlconf_module.urlpatterns: File “/usr/lib/python2.5/site-packages/django/core/urlresolvers.py”, line 262, in geturlconf_module raise ImproperlyConfigured, “Error while importing URLconf %r: %s” % (self.urlconf_name, e) django.core.exceptions.ImproperlyConfigured: Error while importing URLconf ‘urls’: Signal receivers must accept keyword arguments (kwargs).
FastCGI тут при чём? :) Там HTTP. :-)
А что, runserver работает? ;) Обновление должно помочь.
Да ни при чём тут и fapws. В 1.0alpha1 отрефакторили диспатчер сигналов в джанге. Они стали почти в два раза шустрее, но api сменилось. Собсна, это глюк самого byteflow.
А где я сказал, что фапвс тут при чём? Ты невнимательно прочёл. :) Вообще я хотел сказать, что я это уже фиксил, вот и всё.
а ты имел ввиду “обновите byteflow”. А мне почудилось “обновите fapws” oO
да, runserver работает отлично. А fapws2 — фиг. Обновлял byteflow несколько раз, думал не проходит обновление.
в urls.py что то вроде
import django; import sys; sys.stderr.write(''.join(django.__file__, '\n')); sys.stderr.flushвас скорее всего удивит ;)
Точно что-то с
sys.path— у меня последняя джанга (ревизия “russellm: Fixed #8475 …”) работает с последним byteflow без всяких проблем. Fapws2 в том числе.ps aux|grep run
18538 26682 2.2 0.7 22600 15744 ? S Aug02 453:04 python run.py
Cogen жрет процессор как фиг знает что, сайт из 1 приложения, который отдает 7 страниц. Это ужос просто, при запуске через FastCgi сайт сожрет столько процессора только через 2-3 года.
или лыжи не едут или я..
О да, я тоже обращал внимание, но не то, чтоб очень очень. Похоже, лыжи такие. :\
Люди, а поделитесь кто-нибудь fawps2, а то издох сайт www.opensource4you.com
Фу ты, не туда написал коммент.
http://my.piranha.org.ua/fapws2.tar.bz2
йей! спасибо )
www.opensource4you.com в дауне
http://my.piranha.org.ua/fapws2.tar.bz2 ошибка 404
http://piranha.org.ua/blog/2008/10/01/fapws2/
Comment form for «WSGI серверы кратко»