About Blog Dev | Alfa Romeo SZ Conkeror wishlist

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 ядра, зря пропадают с апачем только… :-)

Add post to: Delicious Reddit Slashdot Digg Technorati Google
Comment post

Comments

slav0nic 31.07.2008 16:25

Сашко, а под виндой cogen ты и не запустишь, так как epoll — чисто линуксовый механизм;) и под freebsd тож, там kqueue

/me пока-что остановился на cogen, траблов не наблюдаю, да и код иногда интересно покурить =) а c С тяжко как-то

reply
Alexander Solovyov 31.07.2008 16:40

Сашко, а под виндой cogen ты и не запустишь, так как epoll — чисто линуксовый механизм;)

А, я что-то увлёкся. :) Но cogen для винды юзает iocp просто, вот и всё. А во фре — таки kqueue.

reply
Salvator 31.07.2008 17:08

А под nginxовским mod_wsgi не пробывал?

reply
Alexander Solovyov 31.07.2008 17:29

Нет, руки не дошли. К сожалению, его для джанги в продакшене особо не поиспользуешь — он же блокирует при случае весь процесс nginx’а, а это не очень весело.

reply
Иван Сагалаев 31.07.2008 21:37

Вот тут не понял:

Тем более у моего VPS целых 4 ядра, зря пропадают с апачем только… :-)

Почему пропадают-то? Раз он плодит отдельные процессы, то ОС нормально раскидает их на все доступные ядра.

reply
Alexander Solovyov 31.07.2008 23:57

Не раскидает, потому что я юзаю фичу mod_wsgi — daemon mode. При этом вся джанга выделяется в один отдельный процесс (ты если в результаты посмотришь, можешь их увидеть запущенные под моим пользователем, а не под апачевским), и, соответственно, юзает только одно ядро. Зато апачевские детки маленькие получаются, без питона инсайд. :)

reply
Vadim Fint 2.08.2008 15:44

ну привет

WSGIDaemonProcess ipidevtrac user=ipidevtrac group=nogroup processes=4 threads=16

?

на самом деле при daemon режиме mod_wsgi форкается как раз вместе с питоном внутри. Зато не грузится и парсистся каждый раз, а просто отправляет wsgi на обработку существующему форку. При этом может ещё и потоки создавать (питоновские, т.е. аккурат в питоновском потоке вызывает application(env, get_response)) чтобы долгие запросы не блочили весь форк.

only worker_mpm конечно.

reply
Alexander Solovyov 3.08.2008 11:16

Чорт, а слона-то я и не заметил. Я как-то абсолютно пропустил processes. :\

В общем, попробовал с processes=4 threads=16, выходит 25 запросов в секунду (24.8-24.97). Но при этом возникает 4 процесса, каждый по 30 мегов. : processes=2 threads=4 даёт результаты получше (25.5), и эти два процесса едят мегов по 22-23, что уже явно лучше.

В общем, апач — не аутсайдер, но пока cogen и fapws2 — быстрее. А насколько апач быстр по сравнению с ними у тебя? Не хочешь запустить ab у себя?

Не кажется мне, что он вот так возьмёт и ни с чего обгонит.

reply
Vadim Fint 4.08.2008 10:39

конечно просто так он не обгонит — с чего бы это :). Апач надо очень грамотно собирать, не включая огромную кучу ненужных модулей. Часто я делаю лишь autoindex alias dir logio log_config rewrite so mime authz_host info env setenvif negotiation — мне этого за глаза хватает (в дефолтной поставке модулей раза в три поболе). Только статическая линковка. Ещё к этому всему надо грамтно настроить worker mpm — по дефолту там очень щадящие настройки.

Если настроение будет — прогоню тест, похожий на твой.

reply
Alexander Solovyov 4.08.2008 11:05

Я в курсе про собирание без лишних модулей, но возиться мне лень. :) Проще разобраться с runit’ом и использовать fapws2.

Ну в общем если сделаешь, то это будет хорошо. :)

reply
Андрей Стромнов 1.08.2008 8:09

Интересно, что в cogen написано: “HTTP handling code taken from the CherryPy WSGI server”. Выигрыш, таким образом, получается именно в несколько другой организации обработки запросов.

reply
Alexander Solovyov 1.08.2008 12:39

Да, прикольная тема. Я ещё хочу yield потестировать, но пока с ним траблы есть, вот с автором переписываюсь…

reply
Eugene Lazutkin 18.08.2008 18:58

Запости пожалуйста результаты.

reply
Vadim Fint 2.08.2008 15:46

Что то я не пойму зачем ставить nginx перед апачем? apache + worker_mpm + mod_wsgi2 рвёт на моей машинке любые варианты с не-на-си написанными серверами.

reply
Alexander Solovyov 3.08.2008 11:24

У меня вот прямо сейчас fapws2 в среднем 1800 мс на запрос, апач — 1980. У питоновского когена — 1810, при этом оно не может загрузить проц на 100% — колеблется 97-98 постоянно.

reply
Vadim Fint 4.08.2008 10:40

1.8сек на запрос?! При столь тяжелой бизнес-логике производительность сервера толком ничего не меняет (:

reply
Alexander Solovyov 4.08.2008 11:04

Ога, я сча решил плюнуть и протестировать их на тупом приложении, которое делает return HttpResponse("hello world"). Но пока нету настроения написать и опубликовать что-то, а вкратце — fapws2 всех, кроме когена, в два раза обгоняет. Коген где-то на 20% медленнее.

reply
Dyadya Zed 7.08.2008 19:45

Александр, а как получилось собрать libevent? Я на убунте пробовал собрать — что-то не вышло.

reply
Alexander Solovyov 7.08.2008 22:59

Я соврал. Fapws2 и mod_wsgi рулят, cogen отстаёт в 2 раза, остальные ещё медленнее.

reply
Vadim Fint 8.08.2008 1:42

я много копался в исходнике mod_wsgi.c. Там просто нечему тормозить (:

Причём, все же, и fapws2 с его libevent он, скорее всего, может обогнать при правильной настройке. Я уже запланировал сей бенчмарк на выходные ))

reply
Alexander Solovyov 8.08.2008 9:37

Давай-давай, у меня на этом приложении вышло 3900 запросов для fapws2 и 3500 для mod_wsgi при такой настройке:

WSGIScriptAlias / /home/piranha/dev/web/perftest/django.wsgi

:D С демон-модом вышло 3100.

reply
Dyadya Zed 7.08.2008 21:43

Как поставить fapws2 под убунтой? Нашел libevent в исходниках, скомпилировал, но не заработало.

Есть какой-то более быстрый путь?

reply
Alexander Solovyov 7.08.2008 22:37

Ну, у меня libevent 1.4.6 скомпилировался очень просто. ./configure && make && make install. А что значит “не заработало”?

reply
Vadim Fint 8.08.2008 1:43

1.4.3 пока лучше — в 1.4.4..1.4.6 народ ещё не уверен.

reply
Dyadya Zed 9.08.2008 17:39

вот ошибка.. Поставил 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’:

reply
Alexander Solovyov 10.08.2008 12:05

Ну собственно оно хочет, чтоб сорцы либевента лежали в ./libevent. Так что либо переложи, либо измени путь. :)

reply
Dyadya Zed 11.08.2008 10:26

Спасибо, все получилось. По дороге пришлось в setup.py исправить путь к libevent.so с /usr/lib/libevent.so на /usr/local/lib/libevent.so

reply
Dyadya Zed 11.08.2008 16:56

Попробовал запустить 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..

reply
Alexander Solovyov 11.08.2008 20:36

Аа, я забыл автору патч отправить. Замени res.header.items на res.items пока, а я тут с автором всё дообсуждаю.

reply
Dyadya Zed 17.08.2008 23:09

Как можно вместе запустить 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).

reply
Alexander Solovyov 23.08.2008 15:32

Как можно вместе запустить fapws2 и nginx или fapws2 и lighthttpd? Только через fastcgi или еще можно как-то?

FastCGI тут при чём? :) Там HTTP. :-)

django.core.exceptions.ImproperlyConfigured: Error while importing URLconf ‘urls’: Signal receivers must accept keyword arguments (kwargs).

А что, runserver работает? ;) Обновление должно помочь.

reply
Vadim Fint 23.08.2008 15:41

Да ни при чём тут и fapws. В 1.0alpha1 отрефакторили диспатчер сигналов в джанге. Они стали почти в два раза шустрее, но api сменилось. Собсна, это глюк самого byteflow.

reply
Alexander Solovyov 23.08.2008 15:43

А где я сказал, что фапвс тут при чём? Ты невнимательно прочёл. :) Вообще я хотел сказать, что я это уже фиксил, вот и всё.

reply
Vadim Fint 23.08.2008 15:44

а ты имел ввиду “обновите byteflow”. А мне почудилось “обновите fapws” oO

reply
dyadyazed 24.08.2008 1:19

да, runserver работает отлично. А fapws2 — фиг. Обновлял byteflow несколько раз, думал не проходит обновление.

reply
Vadim Fint 24.08.2008 3:07

в urls.py что то вроде

import django; import sys; sys.stderr.write(''.join(django.__file__, '\n')); sys.stderr.flush

вас скорее всего удивит ;)

reply
Alexander Solovyov 24.08.2008 11:25

Точно что-то с sys.path — у меня последняя джанга (ревизия “russellm: Fixed #8475 …”) работает с последним byteflow без всяких проблем. Fapws2 в том числе.

reply
L0rda 16.08.2008 18:10

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 года.

или лыжи не едут или я..

reply
Alexander Solovyov 16.08.2008 20:15

О да, я тоже обращал внимание, но не то, чтоб очень очень. Похоже, лыжи такие. :\

reply
Pavel 2.09.2008 15:05

Люди, а поделитесь кто-нибудь fawps2, а то издох сайт www.opensource4you.com

reply
Pavel 2.09.2008 15:06

Фу ты, не туда написал коммент.

reply
Pavel 2.09.2008 17:51

йей! спасибо )

reply
bergamot 30.10.2008 8:20

www.opensource4you.com в дауне

http://my.piranha.org.ua/fapws2.tar.bz2 ошибка 404

reply

Comment form for «WSGI серверы кратко»

Required. 30 chars of fewer.

Required.

Comment post