Библиотека сайта rus-linux.net
Библиотека Warp
Глава 11 из книги "Производительность приложений с открытым исходным кодом".
Оригинал: Warp
Авторы: Kazu Yamamoto, Michael Snoyman, Andreas Voellmy
Перевод: Н.Ромоданов
Архитектура библиотеки Warp
Библиотека Warp является HTTP-движком интерфейса веб-приложений (Web Application Interface - WAI). Она запускает приложения WAI поверх протокола HTTP. Как уже было сказано выше, Yesod и mighty являются примерами приложений WAI, что проиллюстрировано на рис.11.6.
Рис.11.6: Интерфейс веб приложения (WAI)
Тип приложения WAI выглядит следующим образом:
type Application = Request -> ResourceT IO Response
В языке Haskell, типы аргументов функций разделяются стрелками, указывающими вправо, а самый правый тип является типом возвращаемого значения. Так что, мы можем интерпретировать определение следующим образом: приложение WAI Application
получает запрос Request
и возвращает Response
, используемый в контексте, где допустимы операции ввода/вывода и реализовано хорошее управление ресурсами.
После того, как произойдет новое подключение HTTP, для этого подключения будет создан специальный пользовательский поток. Он сначала получает HTTP-запрос от клиента и, анализируя его, создает запрос Request
. Затем библиотека Warp передает запрос Reques
t в приложение WAI и получает от него ответ Response
. Наконец, Warp строит HTTP-ответ, который зависит от значения ответа Response
, и отправляет его обратно клиенту. Это показано на рис.11.7.
Рис.11.7: Архитектура библиотеки Warp
Пользовательский поток повторяет по мере необходимости эту процедуру и завершается, когда подключение от клиента закрывается или принимается неправильный запрос. Поток завершает свою работу также в случае, если по истечении определенного периода времени не будет получено требуемое количество данных (т.е. когда происходит тайм-аут).
Производительность Warp
Прежде, чем мы объясним, как можно повысить производительность библиотеки Warp, мы хотели бы показать результаты работы нашего бенчмарка. Мы измерили пропускную способность сервера mighty
версии 2.8.4 (с Warp версии 1.3.8.1) и сервера nginx версии 1.4.0. Наша среда тестирования выглядела следующим образом:
- Две «12-ти ядерные» машины (Intel Xeon E5645, два сокета, 6 ядер на каждый процессор), подключенные с помощью сети Ethernet с пропускной способностью в 1 Гбит.
- Одна машина, на которой работает Linux версии 3.2.0 (Ubuntu 12.04 LTS).
- Еще одна машина, на которой работает FreeBSD 9.1.
В прошлом мы выполняли несколько бенчмарков с помощью тестовых инструментальных средств и нашим любимым был httperf
. Поскольку в нем используется команда select()
и он является просто программой, состоящей из единственного процесса, то когда мы пытаемся измерять серверы HTTP на многоядерных машинах, он достигает границ своей производительности. Поэтому мы перешли на weighttp
, который базируется на вызове команды libev
(семейство epoll
) и может использовать несколько нативных потоков. Мы использовали weighttp
во FreeBSD следующим образом:
weighttp -n 100000 -c 1000 -t 10 -k http://<адрес_ip>:<номер_порта>/
Это означает, что было установлено 1000 HTTP-подключений и в каждом подключении отправлялось по 100 запросов. Для того, чтобы справиться с этой работой, было порождено 10 нативных потоков.
Целевые веб-серверы были откомпилированы на Linux. На все запросы возвращался один и тот же файл index.html
. Мы использовали страницу index.html
сервера nginx
, размер которой составляет 151 байт.
Поскольку в Linux/FreeBSD есть много параметров управления, нам нужно было тщательно настроить эти параметры. Вы можете найти хорошее введение в настройку параметров Linux по ссылке ApacheBench & HTTPerf. Мы тщательно настроили как сервер mighty
, так и сервер nginx
следующим образом:
- включили кэширование файловых дескрипторов
- отключили ведение журнала регистрации
- отключили ограничение по скорости
Результат следующий:
Рис.11.8: Производительность Warp
На оси x показано количество рабочих процессов, а на оси у показана пропускная способность, измеряемая числом запросов в секунду.
- Сервер mighty 2.8.4 (GHC 7.7): откомпилирован с помощью компилятора GHC версии 7.7.20130504 (который должен был быть компилятором GHC версии 7.8). В нем используется менеджер параллельного ввода/вывода только с одним рабочим процессом. Параметры времени работы компилятора:
+RTS -qa -A128m -N<x>
, где<x>
- количество ядер, а128m
- размер выделяемой области памяти, используемой сборщиком мусора. - Сервер mighty 2.8.4 (GHC 7.6.3): откомпилирован с помощью компилятора GHC версии 7.6.3 (которая является последней стабильной версией).
Продолжение статьи: Ключевые принципы.