- PVSM.RU - https://www.pvsm.ru -

Анализ производительности WSGI-серверов: Часть вторая

Данная статья является переводом статьи Кевина Голдберга «A Performance Analysis of Python WSGI Servers: Part 2» dzone.com/articles/a-performance-analysis-of-python-wsgi-servers-part [1] с небольшими дополнениями от переводчика.

image

Введение

В первой части [2] этой серии Вы познакомились с WSGI и с шестью наиболее популярными по мнению автора WSGI-серверами. В этой части Вам будет показан результат анализа производительности этих серверов. С этой целью была создана специальная тестовая песочница.

Конкурсанты

Из-за нехватки времени исследование было ограничено шестью WSGI-серверами. Весь код с инструкциями по запуску для этого проекта размещен на GitHub [3]. Возможно со временем проект будет расширяться и будут представлены анализы производительности для других WSGI-серверов. Но пока речь пойдёт о шести серверах:


  1. Bjoern описывает себя как « сверхбыстрый WSGI-сервер» и может похвастаться тем, что это «самый быстрый, самый маленький и легкий WSGI-сервер». Мы создали небольшое приложение [4], использующее большинство параметров библиотеки по умолчанию.
  2. CherryPy - чрезвычайно популярный и стабильный фреймворк и WSGI-сервер. Этот небольшой скрипт [5] использовался для обслуживания нашего образца приложения через CherryPy.
  3. Gunicorn был вдохновлен сервером Unicorn от Ruby (отсюда и название). Он скромно утверждает, что он «просто реализован, легок в использовании и довольно быстрый». В отличие от Bjoern и CherryPy, Gunicorn является автономным сервером. Мы создали его с помощью этой команды [6]. Параметр «WORKER_COUNT» был установлен в два раза больше доступных ядер процессора, плюс один. Это было сделано на основании рекомендаций из документации Gunicorn [7].
  4. Meinheld - это высокопроизводительный WSGI-совместимый веб-сервер, который утверждает, что он легкий. Основываясь на примере, указанном на сайте сервера, мы создали своё приложение [8].
  5. mod_wsgi создан тем же создателем, что и mod_python. Подобно mod_python, он доступен только для Apache. Однако он включает инструмент под названием «mod_wsgi express», который создаёт минимально возможный инстанс Apache. Мы сконфигурировали и использовали mod_wsgi express с помощью этой команды [9]. Чтобы соответствовать Gunicorn, мы настроили mod_wsgi т.о, чтобы создать worker-ов вдвое больше чем ядер процессора.
  6. uWSGI - полнофункциональный сервер приложений. Как правило, uWSGI сопрягается с прокси-сервером (например: Nginx). Однако, чтобы лучше оценить производительность каждого сервера, мы попытались использовать только голые серверы и создали двух worker-ов [10] для каждого доступного ядра процессора.

Бенчмарк

Чтобы сделать тест максимально объективным, был создан Docker [11]-контейнер для изоляции тестируемого сервера от остальной части системы. Также использование Docker-контейнера гарантировало, что каждый запуск начинается с чистого листа.

Сервер:

  • Изолирован в Docker-контейнере.
  • Выделено 2 ядра процессора.
  • Оперативная память контейнера была ограничена до 512 МБ.

Тестирование:

  • wrk [12], современный инструмент HTTP-бенчмаркинга, запускал тесты.
  • Серверы были протестированы в произвольном порядке с увеличением числа одновременных соединений в диапазоне от 100 до 10000.
  • wrk был ограничен двумя ядрами ЦПУ, не используемыми Docker.
  • Каждый тест длился 30 секунд и повторялся 4 раза.

Метрика:

  • Среднее количество постоянных запросов, ошибок и задержек предоставлялось wrk.
  • Встроенный в Docker, мониторинг показывал уровни использования ЦПУ и ОЗУ.
  • Самые высокие и самые низкие показания были отброшены, а остальные значения были усреднены.
  • Для любопытных мы отправили полный скрипт на GitHub [13].

Результаты

Все исходные показатели производительности были включены в репозиторий проекта [14], а также предоставлен сводный CSV-файл [15]. Также для визуализации были созданы графики в среде Google-doc [16].

Зависимость RPS от числа одновременных соединенинй

На этом графике показано среднее количество одновременных запросов; Чем выше число, тем лучше.

image

image

  • Bjoern: Явный победитель.
  • CherryPy: Несмотря на то, что он написан на чистом Python, он был лучшим исполнителем.
  • Meinheld: Отличные показатели, учитывая скудные ресурсы контейнера.
  • mod_wsgi: Не самый быстрый, но производительность была последовательной и адекватной.
  • Gunicorn: Хорошая производительность при более низких нагрузках, но прослеживается борьба при большом количестве соединений.
  • uWSGI: Разочаровал плохими результатами.

ПОБЕДИТЕЛЬ: Bjoern

Bjoern

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

uWSGI

Мы были разочарованы слабыми результатами uWSGI. Мы ожидали, что он окажется в лидерах. Во время тестирования мы заметили, что логи uWSGI печатает на экране, и первоначально мы объяснили отсутствие производительности дополнительной работой, которую выполнял сервер. Тем не менее, даже после добавленной опции «--disable-logging», uWSGI по-прежнему является самым медленным сервером.

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

Задержка

Задержка — это количество времени, прошедшего между запросом и его ответом. Более низкие цифры — лучше.

image

  • CherryPy: Хорошо справлялся с нагрузкой.
  • Bjoern: В целом низкие задержки, но лучше работает при меньшем количестве одновременных соединений.
  • Gunicorn: хорош и последователен.
  • mod_wsgi: Средняя производительность, даже при большом количестве одновременных соединений.
  • Meinheld: В целом, приемлемая производительность.
  • uWSGI: uWSGI снова на последнем месте.

ПОБЕДИТЕЛЬ: CherryPy

Использование ОЗУ

Эта метрика показывает требования к памяти и «легкость» каждого сервера. Более низкие цифры — лучше.

image

  • Bjoern: Чрезвычайно легкий. Использует всего лишь 9 МБ ОЗУ для обработки 10 000 одновременных запросов.
  • Meinheld: Такой же как Bjoern.
  • Gunicorn: Умело справляется с высокими нагрузками с едва заметным потреблением памяти.
  • CherryPy: Первоначально нуждался в небольшом количестве оперативной памяти, но её использование стремительно увеличивалось с ростом нагрузки.
  • mod_wsgi: На более низких уровнях он был одним из наиболее интенсивных в памяти, но оставался довольно последовательным.
  • uWSGI: Очевидно, что у тестируемой нами версии проблемы с количеством потребляемой памяти.

ПОБЕДИТЕЛИ: Bjoern и Meinheld

Количество ошибок

Ошибка возникает, когда сервер падает, прерывается или истекает время запроса. Чем ниже, тем лучше.

image

Для каждого сервера мы рассчитали отношение общее отношение количества запросов к числу ошибок:

  • CherryPy: коэффициент ошибок около 0, даже при высоком количестве соединений.
  • Bjoern: Ошибки встречались, но это компенсировалось количеством обработанных запросов.
  • mod_wsgi: Хорошо работает с приемлемой частотой ошибок 6%.
  • Gunicorn: Работает с 9-процентной частотой ошибок.
  • uWSGI: Учитывая низкое количество запросов, которые он обслуживал, он оказался с 34-процентной частотой ошибок.
  • Meinheld: Упал на более высоких нагрузках, выбросив более 10 000 ошибок во время самого требовательного теста.

ПОБЕДИТЕЛЬ: CherryPy

Использование ЦПУ

Высокое использование ЦПУ не является хорошим или плохим, если сервер работает хорошо. Однако, это даёт некоторые интересные сведения о работе сервера. Поскольку использовались два ядра ЦПУ, максимальное возможное использование составляет 200 процентов.

image

  • Bjoern: однопоточный сервер, о чем свидетельствует его последовательное использование на 100% ЦПУ.
  • CherryPy: многопоточный, но застрял на 150-ти процентах. Это может быть связано с GIL Python [17].
  • Gunicorn: использует несколько процессов с полным использованием ресурсов ЦПУ на более низких уровнях.
  • Meinheld: однопоточный сервер, использующий ресурсы ЦПУ как Bjoern.
  • mod_wsgi: Многопоточный сервер использующий все ядра ЦПУ на протяжении всех измерений
  • uWSGI: очень низкое использование ЦПУ. Потребление ресурсов ЦПУ не превышает 50-ти процентов. Это одно из доказательств того, что uWSGI неправильно сконфигурирован.

ПОБЕДИТЕЛЬ: Нет, поскольку это скорее наблюдение в поведении, чем сравнение в производительности.

Заключение

Подведем итог! Вот некоторые общие идеи, которые можно почерпнуть из результатов каждого сервера:

  • Bjoern: Оправдывает себя как «супербыстрый, ультралегкий WSGI-сервер».
  • CherryPy: Высокая производительность, маленькое потребление памяти и маленькое количество ошибок. Неплохо для чистого Python.
  • Gunicorn: Хороший сервер для средних нагрузок.
  • Meinheld: Хорошо работает и требует минимальных ресурсов. Тем не менее, борется с более высокими нагрузками.
  • mod_wsgi: Интегрируется в Apache и отлично работает.
  • uWSGI: Очень разочаровал. Либо мы неправильно сконфигурировали uWSGI, либо версия, которую мы установили, имеет базовые ошибки.

Автор: Степан Филатов

Источник [18]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/python/296518

Ссылки в тексте:

[1] dzone.com/articles/a-performance-analysis-of-python-wsgi-servers-part: https://dzone.com/articles/a-performance-analysis-of-python-wsgi-servers-part

[2] первой части: https://habr.com/post/426957/

[3] размещен на GitHub: https://github.com/omedhabib/WSGI_Benchmarks

[4] небольшое приложение: https://gist.github.com/omedhabib/c3c8ff74ec3993740e80d7235251e73a

[5] небольшой скрипт: https://gist.github.com/omedhabib/1c6bd85bd83cc065c41f8a428865963f

[6] этой команды: https://gist.github.com/omedhabib/8de8a5a7739726a0ab142a0f85295135

[7] документации Gunicorn: http://docs.gunicorn.org/en/stable/settings.html#workers

[8] своё приложение: https://gist.github.com/omedhabib/d638e213af0f843580e5ca7724005ac6

[9] этой команды: https://gist.github.com/omedhabib/8f0e6f7d0103780d3f6f0f73108a86b2

[10] создали двух worker-ов: https://gist.github.com/omedhabib/0e61685d14cd019622c02817034f26e3

[11] Docker: https://habr.com/post/309556/

[12] wrk: https://github.com/wg/wrk

[13] GitHub: https://github.com/omedhabib/WSGI_Benchmarks/blob/master/benchmark.sh

[14] были включены в репозиторий проекта: https://github.com/omedhabib/WSGI_Benchmarks/tree/master/round1

[15] CSV-файл: https://github.com/omedhabib/WSGI_Benchmarks/blob/master/results.csv

[16] Google-doc: https://docs.google.com/spreadsheets/d/1HVNNOIbZZOmFs9BHM9PmB9Ngf3hpPqMeiBYjJTWs3xY/pubhtml

[17] GIL Python: https://habr.com/post/84629/

[18] Источник: https://habr.com/post/427217/?utm_source=habrahabr&utm_medium=rss&utm_campaign=427217