После выхода моей предыдущей статьи о методах высокопроизводительной настройки проектов на RoR, я получил море сообщений/писем и поговорил с кучей народу через IM и многие сообщения касались логических или методических ошибок в процессе тестирования или содержали в себе просьбу расширить или изменить параметры тестирования. Именно поэтому я решил провести новое тестирование - более глубокое и намного более широкое в плане охвата различных решений. В этой статье Вы сможете ознакомиться с методикой тестирования и, конечно же, с результатами проведенных тестов. Если Вас интересуют детали настройки ПО в отдельных тестах, Вы можете заглянуть в раздел сайта, посвещенный “Ruby On Rails” и прочесть отдельные сообщения из серии “В поисках оптимального решения” о каждом из тестировавшихся подходов к запуску rails-приложений (статьи о конфигурации будут готовы в течение ближайших нескольких дней).

Честно говоря, когда я начинал все это тестирование, моей основной целью был поиск наиболее оптимального решения для инсталляции моего проекта. Но позже, блягодаря критике Дмитрия Штефлюка, я решил проводить тестирование, стараясь выжать максимум из каждого теста с целью найти максимальную теоретическую скорость, которую я могу ожижать от моих серверов при работе с Ruby on Rails. Поэтому Вы можете интерпретировать результаты тестирования с двух различных точек зрения: как простое сравнение производительности различных решений или как оценку сверху возможной производительности вашего решения (конечно, вы можете получить больше от этих решений если будете использовать более сложные схемы вроде “nginx/lighttpd для статики + rails для динамики”, но это тетсирование проводилось только для динамики без использование различных схем кеширования).

В первую очередь хотелось бы описать платформу, на которой производилось тестирование. Наш development-сервер имеет следующую аппаратно-программную конфигурацию:

  • CPU: 4 x XEON CPUs
  • Память: 4 Gb of RAM
  • OS: Debian GNU/Linux Testing с последним 2.6 ядром.
  • Ruby: ruby 1.8.4 (2005-12-24) [i486-linux] из репозитория Debian Testing.
  • Rails: Rails 1.1.6 проинсталлирован из gem.

Все тесты проводились на простом rails-приложениис одним single-action контроллером:

class TestController < ApplicationController
  def hw
    @hello = "Hello, world!"
    @time = Time.now()
  end
end

м простым view:

<h1>Test#hw</h1>

<p>Hello: <%= @hello %></p>
<p>Time: <%= @time %></p>

Rails Framework был запущен с настройками по-умолчанию для production mode. Тесты были выполнены при помощи программы ab (Apache Benchmark) со следующими параметрами:

$ ab -c 100 -n 10000 http://SERVERIP:PORT/test/hw

где PORT - это специфичный для каждого теста номер порта, на котором принимаются запросы.

Я решил не добавлять никакого I DB-related кода, т.к. моей целью было тестирование проиводительности движка Ruby On Rails, а не mysql/postgres/oracle/etc. Простой код, простые тесты, простые и понятные результаты.

Замечение: Перед каждым тестом все файлы из каталога tmp/sessions удалялись, т.к. после огромного количества запросов там скапливается очень много файлов и на результаты теста начинают влиять проблемы файловых систем. Потому, если вы захотите повторить проделанные мною тесты на своей платформе, очищайте этот каталог перед каждым тестом.

В процессе работы тестов я наблюдал за сервером при помощи top/iostat/vmstat с целью понять, почему результаты получились именно такими… и именно поэтому во всех тестах с учатием fastcgi/proxy/lsapi использовались 4 backend-процесса - у сервера 4 CPU и 4 процесса показали себя наиболее производительно по сравнению с 2/5/8/10.

Итак, позвольте мне кратно описать протестированные конфигурации перед тем, как показать вам результаты тестирования (ссылки с названий тестов позже будут вести на более детальные описания конфигураций).

  1. WEBrick/1.3.1 - Был протестирован с единственной целью - получить некоторую величину, с которой можно будет сравнивать все остальные результаты тестов.
  2. mongrel (single process) - Этот тест был проведен для того, чтобы получить информацию, насколько сильно меняет производительность использование одного процесса mongrel без балансирующего ПО.
  3. lighttpd (4 mongrels) - Тест на качество реализации в lighttpd балансировки нагрузки между несколькими tcp backend серверами.
  4. lighttpd (4 fastcgi processes) - Тест на качество реализации в lighttpd балансировки нагрузки между несколькими fastcgi серверами.
  5. nginx (4 mongrels) - Тест на качество реализации в nginx балансировки нагрузки между несколькими tcp backend серверами.
  6. nginx (4 fastcgi processes) - Тест на качество реализации в nginx балансировки нагрузки между несколькими fastcgi серверами.
  7. pen (4 mongrels) - Тест на качество реализации в pen балансировки нагрузки между несколькими tcp backend серверами.
  8. pound (4 mongrels) - Тест на качество реализации в pound балансировки нагрузки между несколькими tcp backend серверами.
  9. haproxy (4 mongrels) - Тест на качество реализации в haproxy балансировки нагрузки между несколькими tcp backend серверами.
  10. apache 2.0 (4 fastcgi processes) - Тест на качество реализации в apache 2.0 балансировки нагрузки между несколькими fastcgi серверами.
  11. LiteSpeed (4 lsapi instances) - Этот экзотический продукт был проверен только из-за того, что в коментариях к прошлому тестированию я увидет просьбу проверить его. Веб-сервер LiteSpeed содержит в себе какой-то SAPI модуль для ruby который, AFAIU, работает как обычный FastCGI, но с некоторыми улучшениями в плане производительности. Но, к несчастью, оптимизированная версия стоит некоторого количества денег, что значительно ограничивает круг ее пользователей (у них есть бесплатная версия, но если вам нужна от сервера производительность, но придется заплатить достаточно много денег).

Ну, вот и настало время представления результатов тестирования. Прежде всего хочу представить результаты в табличном виде (screenshot из Excel-таблицы:

Ruby On Rails Deployment Schemes

Если Вам приятнее анализировать результаты в графическом представлении, Вы можете взглянуть на следующую диаграмму, показывающую QPS (количество запросов в секунду) для всех тестов:

Ruby On Rails Deployment Schemes Performance Diagram

Говоря о результатах, Я могу скзаать, что все они были предсказуемы - TCP действительно медленнее, чем unix sockets, которые использовались в тестах с fastcgi. Поэтому все тесты, в которых общение с backend-сервером происходит через tcp, имеют QPS ниже, чем основанные на unix socket. Но должен обратить Ваше внимание на следующий факт: общение frontend-backend через tcp тоже дает отличную производительность сохраняя при этом практически не ограниченную масштабируемость решения и возможность переносить backend-сервера между физическими машинами без каких-либо проблем. Итак, если вам нуобходима абсолютно максимальная производительность от одного сервера, я бы порекомендовал использовать nginx с fastcgi backend-процессами. Но если вам необходима масштабируемость, вы можете использовать nginx с mongrel-серверами в качестве backend-процессов.